How Tomcat works 6: Lifecycle

  1. 概述

    Catalina由许多组件组成,当容器启动时,这些组件都需要启动。当容器停止时,所有组件都需要做清除动作。如:调用所有servlet的detroy动作,session manager把session对象存入第二存储位置。启动和停止组件的持续性机制就是实现Lifecycle接口的实现类。

    Lifecycle接口的实现组件可以触发一个或多个事件(Events):

    与启动相关:BEFORE_START_EVENT, START_EVENT, AFTER_START_EVENT

    与停止相关:BEFORE_STOP_EVENT, STOP_EVENT, AFTER_STOP_EVENT

    LifecycleListener接口的实现类能够监听这些Events

  1. Lifecycle接口:

    Catalina的设计允许组件包含其他组件,Lifecycle接口可以实现单独的启动和停止机制可以启动和停止所有的组件。

(1)接口代码:

		package com.cisco.tomcat.lifecycle;
		
		import org.apache.catalina.LifecycleException;
		
		public interface Lifecycle {
			public static final String START_EVENT = "start";
			public static final String BEFORE_START_EVENT = "before_start";
			public static final String AFTER_START_EVENT = "after_start";
			public static final String STOP_EVENT = "stop";
			public static final String BEFORE_STOP_EVENT = "before_stop";
			public static final String AFTER_STOP_EVENT = "after_stop";
			
			void addLifecycleListener(LifecycleListener lifecycleListener);
			void removeLifecycleListener(LifecycleListener lifecycleListener);
			LifecycleListener[] findLifecycleListeners();
			
			void start() throws LifecycleException;
			void stop() throws LifecycleException;
		}
  1. LifecycleListener接口:
package com.cisco.tomcat.lifecycle;



public interface LifecycleListener {

void LifecycleEvent(LifecycleEvent lifecycleEvent);

}
  1. LifecycleEvent接口:

package com.cisco.tomcat.lifecycle;

 

import java.util.EventObject;

 

public final class LifecycleEvent extends EventObject{

private static final long serialVersionUID = -4784952890250618928L;

private Object data;private Lifecycl

e lifecycle;

private String type;



public LifecycleEvent(Lifecycle lifecycle, String type) {                

this(lifecycle, type, null);

}



public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {

super(lifecycle);

this.lifecycle = lifecycle;

this.type = type;

this.data = data;

}



public Object getData() {

return data;

}

public Lifecycle getLifecycle() {

return lifecycle;

}

public String getType() {

return type;

}

}

 

  1. LifecycleSupport接口:

package com.cisco.tomcat.lifecycle;

 

public final class LifecycleSupport {

private Lifecycle lifecycle;

private LifecycleListener[] listeners = new LifecycleListener[0];public Lifec

ycleSupport(Lifecycle lifecycle) {

super();

this.lifecycle = lifecycle;                

}



public void addLifecycleListener(LifecycleListener listener) {

// 拷贝所有lifecycleListener数组到临时result变量,result数组长度+1

synchronized (listeners) {

LifecycleListener[] results = new LifecycleListener[listeners.length+1];

for(int i = 0; i<listeners.length; i++) {

results[i] = listeners[i];

}

results[listeners.length] = listener;

listeners = results;

}                

}



public void removeLifecycleListener(LifecycleListener listener) {

synchronized (listeners) {

int n = -1;

for(int i=0; i<listeners.length; i++) {

if(listeners[i] == listener) {

n = i;

break;

}

}

if(n<0) {

return;

}

// 拷贝所有lifecyclelister数组到临时变量,长度-1

LifecycleListener[] results = new LifecycleListener[listeners.length -1];

int j = 0;

for(int i=0; j<listeners.length; j++) {

if(i == n) {

break;

}

results[j] = listeners[i];

j++;

}

listeners = results;

}

}



public LifecycleListener[] findLifecycleListeners() {

return listeners;

}



public void fireLifecycleEvent(String type, Object data) {

// 存储lifecycleEvent从lifecycle获取

LifecycleEvent lifecycleEvent = new LifecycleEvent(lifecycle, type, data);

LifecycleListener[] interested = null;

synchronized (listeners) {

interested = listeners.clone();

}

// 遍历listener,找到匹配event的listener,调用相应动作

for(int i=0; i<interested.length; i++) {

interested[i].LifecycleEvent(lifecycleEvent);

}

}



}

 

  1. Lifecycle应用案例:

(1)UML图:

How Tomcat works 6: Lifecycle

(2)SimpleContext类:

实现了Lifecycle接口,使用LifecycleSupport存储生命周期实例。

package com.cisco.tomcat.lifecycle;



import java.io.IOException;



import javax.servlet.ServletException;



import org.apache.catalina.LifecycleException;

import org.apache.catalina.connector.Request;

import org.apache.catalina.connector.Response;

import org.apache.catalina.core.StandardPipeline;



import com.cisco.tomcat.container.pipeline.Valve;



public class SimpleContext implements Lifecycle, Pipeline, Container {



private LifecycleSupport lifecycle = new LifecycleSupport(this);

private Pipeline pipeline = new SimplePipeline(this);

private boolean started = false;



@Override

public Valve getBasic() {

// TODO Auto-generated method stub

return null;

}



@Override

public void setBasic(Valve basic) {

// TODO Auto-generated method stub



}



@Override

public void addValves(Valve valve) {

// TODO Auto-generated method stub



}



@Override

public Valve[] getValves() {

// TODO Auto-generated method stub

return null;

}



@Override

public void removeValves() {

// TODO Auto-generated method stub



}



@Override

public void invoke(Request request, Response response) throws IOException, ServletException {

pipeline.invoke(request, response);



}



@Override

public void addLifecycleListener(LifecycleListener lifecycleListener) {

lifecycle.addLifecycleListener(lifecycleListener);

}



@Override

public void removeLifecycleListener(LifecycleListener lifecycleListener) {

lifecycle.removeLifecycleListener(lifecycleListener);



}



@Override

public LifecycleListener[] findLifecycleListeners() {

return lifecycle.findLifecycleListeners();

}



@Override

public synchronized void start() throws LifecycleException {

if (started) {

throw new LifecycleException();

}

System.out.println("启动Context容器");

for (Container child : getChildren()) {

((Lifecycle) child).start();

}

((Lifecycle) pipeline).start();



lifecycle.fireLifecycleEvent(START_EVENT, null);



lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

}



@Override

public void stop() throws LifecycleException {

if(!started) {

throw new LifecycleException();

}

lifecycle.fireLifecycleEvent(STOP_EVENT, null);

System.out.println("关闭context容器");

for(Container child : getChildren()) {

((Lifecycle)child).stop();

}

if(pipeline instanceof Lifecycle) {

((Lifecycle)pipeline).stop();

}

lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, data);

}



@Override

public Container[] getChildren() {

// TODO Auto-generated method stub

return null;

}



@Override

public void addChild(Container child) {

// TODO Auto-generated method stub



}



}

(3)SimpleLifecycleListener类:

package com.cisco.tomcat.lifecycle;



public class SimpleLifecycleListener implements LifecycleListener{



@Override

public void LifecycleEvent(LifecycleEvent lifecycleEvent) {

// Lifecycle lifecycle = lifecycleEvent.getLifecycle();

System.out.println("do Event for simpleLifecycle, event is: "+lifecycleEvent.getType());

if(Lifecycle.START_EVENT.equals(lifecycleEvent.getType())) {

System.out.println("Start Event......");

}else if(Lifecycle.STOP_EVENT.equals(lifecycleEvent.getType())) {

System.out.println("Stop Event......");

}

}

}

(4)BootStrap类:

package com.cisco.tomcat.lifecycle;



import java.io.IOException;

import org.apache.catalina.LifecycleException;



public class Bootstrap {

public static void main(String[] args) {

// 添加wrapper到context中,添加listener,启动conext.start()

SimpleContext context = new SimpleContext();

LifecycleListener simpleLifecycleListener = new SimpleLifecycleListener();

SimpleWrapper wrapper = new SimpleWrapper();

context.addChild(wrapper);

context.addLifecycleListener(simpleLifecycleListener);

try {



((Lifecycle)context).start();

System.in.read();

 ((Lifecycle) context).stop();



} catch (LifecycleException e) {

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}



}

}

(5)观察者模式:

How Tomcat works 6: Lifecycle