How Tomcat works 6: Lifecycle
- 概述
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
- 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;
}
- LifecycleListener接口:
package com.cisco.tomcat.lifecycle;
public interface LifecycleListener {
void LifecycleEvent(LifecycleEvent lifecycleEvent);
}
- 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;
}
}
- 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);
}
}
}
- Lifecycle应用案例:
(1)UML图:
(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)观察者模式: