tomcat4.0版本。
生命周期在tomcat中由lifecycle接口表征,容器需要实现这个生命周期接口,这样每一个容器就可以由父容器来掌管生命周期,由父容器启动和终止。
public interface Lifecycle {
// ----------------------------------------------------- Manifest Constants
/**
* The LifecycleEvent type for the "component start" event.
*/
public static final String START_EVENT = "start";
/**
* The LifecycleEvent type for the "component before start" event.
*/
public static final String BEFORE_START_EVENT = "before_start";
/**
* The LifecycleEvent type for the "component after start" event.
*/
public static final String AFTER_START_EVENT = "after_start";
/**
* The LifecycleEvent type for the "component stop" event.
*/
public static final String STOP_EVENT = "stop";
/**
* The LifecycleEvent type for the "component before stop" event.
*/
public static final String BEFORE_STOP_EVENT = "before_stop";
/**
* The LifecycleEvent type for the "component after stop" event.
*/
public static final String AFTER_STOP_EVENT = "after_stop";
// --------------------------------------------------------- Public Methods
/**
* Add a LifecycleEvent listener to this component.
*
* @param listener The listener to add
*/
public void addLifecycleListener(LifecycleListener listener);
/**
* Get the lifecycle listeners associated with this lifecycle. If this
* Lifecycle has no listeners registered, a zero-length array is returned.
*/
public LifecycleListener[] findLifecycleListeners();
/**
* Remove a LifecycleEvent listener from this component.
*
* @param listener The listener to remove
*/
public void removeLifecycleListener(LifecycleListener listener);
/**
* Prepare for the beginning of active use of the public methods of this
* component. This method should be called before any of the public
* methods of this component are utilized. It should also send a
* LifecycleEvent of type START_EVENT to any registered listeners.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
public void start() throws LifecycleException;
/**
* Gracefully terminate the active use of the public methods of this
* component. This method should be the last one called on a given
* instance of this component. It should also send a LifecycleEvent
* of type STOP_EVENT to any registered listeners.
*
* @exception LifecycleException if this component detects a fatal error
* that needs to be reported
*/
public void stop() throws LifecycleException;
}
tomcat中的生命周期目前只有start和stop两个方法。每一方法对应三个事件,由string定义为常量。tomcat中的组件或者容器都有定义父子关系,因此组件实现了该接口,父容器就可以掌管生命周期。
还有一个概念就是监听器。这里我们只关注与生命周期相关的监听器。当我们需要容器在start或者stop时执行某种操作,就需要使用生命周期监听器。本质是一个回调,我们在容器上注册一个监听器,注册时需要以接口的形式指定回调函数:
public interface LifecycleListener {
/**
* Acknowledge the occurrence of the specified event.
*
* @param event LifecycleEvent that has occurred
*/
public void lifecycleEvent(LifecycleEvent event);
}
也即实现这个LifecycleListener。那么容器会在执行每一个与生命周期的方法中调用注册的监听器的回调方法。
下面是生命周期的事件类:
public final class LifecycleEvent
extends EventObject {
// ----------------------------------------------------------- Constructors
/**
* Construct a new LifecycleEvent with the specified parameters.
*
* @param lifecycle Component on which this event occurred
* @param type Event type (required)
*/
public LifecycleEvent(Lifecycle lifecycle, String type) {
this(lifecycle, type, null);
}
/**
* Construct a new LifecycleEvent with the specified parameters.
*
* @param lifecycle Component on which this event occurred
* @param type Event type (required)
* @param data Event data (if any)
*/
public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
super(lifecycle);
this.lifecycle = lifecycle;
this.type = type;
this.data = data;
}
// ----------------------------------------------------- Instance Variables
/**
* The event data associated with this event.
*/
private Object data = null;
/**
* The Lifecycle on which this event occurred.
*/
private Lifecycle lifecycle = null;
/**
* The event type this instance represents.
*/
private String type = null;
// ------------------------------------------------------------- Properties
/**
* Return the event data of this event.
*/
public Object getData() {
return (this.data);
}
/**
* Return the Lifecycle on which this event occurred.
*/
public Lifecycle getLifecycle() {
return (this.lifecycle);
}
/**
* Return the event type of this event.
*/
public String getType() {
return (this.type);
}
}
接下来看看tomcat的容器在执行时是如何触发监听器的,比如ContainerBase中的start方法,ContainerBase是所有容器的公共父类,封了公共方法,自然是实现了生命周期接口。当一个容器被父容器启动时,就会被调用其start方法,start方法在执行前后就会调用一个support的firelifecycleEvent方法来触发事件:
public synchronized void start() throws LifecycleException {
// Validate and update our current component state
if (started)
throw new LifecycleException
(sm.getString("containerBase.alreadyStarted", logName()));
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
addDefaultMapper(this.mapperClass);
started = true;
// Start our subordinate components, if any
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start();
if ((logger != null) && (logger instanceof Lifecycle))
((Lifecycle) logger).start();
if ((manager != null) && (manager instanceof Lifecycle))
((Lifecycle) manager).start();
if ((cluster != null) && (cluster instanceof Lifecycle))
((Lifecycle) cluster).start();
if ((realm != null) && (realm instanceof Lifecycle))
((Lifecycle) realm).start();
if ((resources != null) && (resources instanceof Lifecycle))
((Lifecycle) resources).start();
// Start our Mappers, if any
Mapper mappers[] = findMappers();
for (int i = 0; i < mappers.length; i++) {
if (mappers[i] instanceof Lifecycle)
((Lifecycle) mappers[i]).start();
}
// Start our child containers, if any
Container children[] = findChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Lifecycle)
((Lifecycle) children[i]).start();
}
// Start the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(START_EVENT, null);
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
主意这里的lifecycle对象是一个LifeCycleSupport类型的实例:
/**
* The lifecycle event support for this component.
*/
protected LifecycleSupport lifecycle = new LifecycleSupport(this);
这个类可以看做一个生命周期事件相关的辅助类,负责管理和触发生命周期相关事件的操作。
接下来看看这个support类:
重要的成员变量有:
/**
* The source component for lifecycle events that we will fire.
*/
private Lifecycle lifecycle = null;
/**
* The set of registered LifecycleListeners for event notifications.
*/
private LifecycleListener listeners[] = new LifecycleListener[0];
lifecycle很显然是support实例的服务对象,一个容器会持有一个support实例来帮助它管理这些事件。然后support内部持有一个list来存放所有监听器。
接着是管理监听器的方法:
/**
* Add a lifecycle event listener to this component.
*
* @param listener The listener to add
*/
public void addLifecycleListener(LifecycleListener listener) {
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;
LifecycleListener results[] =
new LifecycleListener[listeners.length - 1];
int j = 0;
for (int i = 0; i < listeners.length; i++) {
if (i != n)
results[j++] = listeners[i];
}
listeners = results;
}
}
在容器内部也有类似的方法,但是内部是通过调用support的add和remove来管理监听器的。
最重要的还是下面的fire方法:
/**
* Notify all lifecycle event listeners that a particular event has
* occurred for this Container. The default implementation performs
* this notification synchronously using the calling thread.
*
* @param type Event type
* @param data Event data
*/
public void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
LifecycleListener interested[] = null;
synchronized (listeners) {
interested = (LifecycleListener[]) listeners.clone();
}
for (int i = 0; i < interested.length; i++)
interested[i].lifecycleEvent(event);
}
从之前的代码中可以看到,容器start和stop时,内部会调用support实例的fire方法,这个方法会调所有监听器的回调方法,从而通知到观察者。观察者可以检测事件是否是自己关注的,进而处理。
下面看下观察者在收到事件通知是如何处理事件的,比如SeverLifecycleListener:
public void lifecycleEvent(LifecycleEvent event) {
Lifecycle lifecycle = event.getLifecycle();
if (Lifecycle.START_EVENT.equals(event.getType())) {
if (lifecycle instanceof Server) {
// Loading additional MBean descriptors
loadMBeanDescriptors();
createMBeans();
}
// We are embedded.
if( lifecycle instanceof Service ) {
if( debug > 0 )
log( "Starting embeded" + lifecycle);
try {
MBeanFactory factory = new MBeanFactory();
createMBeans(factory);
loadMBeanDescriptors();
createMBeans((Service)lifecycle);
} catch( Exception ex ) {
log("Error registering the service", ex);
}
}
/*
// Ignore events from StandardContext objects to avoid
// reregistering the context
if (lifecycle instanceof StandardContext)
return;
createMBeans();
*/
} else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
if (lifecycle instanceof Server) {
destroyMBeans();
}
} else if (Context.RELOAD_EVENT.equals(event.getType())) {
// Give context a new handle to the MBean server if the
// context has been reloaded since reloading causes the
// context to lose its previous handle to the server
if (lifecycle instanceof StandardContext) {
// If the context is privileged, give a reference to it
// in a servlet context attribute
StandardContext context = (StandardContext)lifecycle;
if (context.getPrivileged()) {
context.getServletContext().setAttribute
(Globals.MBEAN_REGISTRY_ATTR,
MBeanUtils.createRegistry());
context.getServletContext().setAttribute
(Globals.MBEAN_SERVER_ATTR,
MBeanUtils.createServer());
}
}
}
}
可以看到确实是一个if块,选出自己感兴趣的事件同时做相关的处理。
其实这里是一个简单的观察者模式的实现,观察者模式的本质也就是回调。