《How Tomcat Works》读书笔记(六)Lifecycle

Tomcat有很多组件,在Tomcat启动的同时,这些组件也应该跟着启动,在Tomcat要停止之前,这些组件需要有机会完成自己的收尾工作.

之前提过servlet的生命周期,从上一节我们知道一个Wrapper代表一个Servlet,一个Context可以有很多个Wrapper.当一个Context要停止,它会调用它的Wrapper的stop方法,Wrapper会调用servlet的destory方法.

一个组件只需实现org.apache.catalina.Lifecycle就可以管理自己的生命周期了。

看一下Lifecycle的接口定义:

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";
    //事件监听器
    public void addLifecycleListener(LifecycleListener listener);
    public LifecycleListener[] findLifecycleListeners();
    public void removeLifecycleListener(LifecycleListener listener);
    //生命周期管理
    public void start() throws LifecycleException;
    public void stop() throws LifecycleException;
}
startstop算是最重要的两个方法了, 父组件在start/stop时会调用它的子组件的start/stop方法,完成启动/停止。

Lifecycle里只有生命周期事件的名称,来看下它的实现: 

public final class LifecycleEvent extends EventObject {
    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;
    }
    private Object data = null;
    private Lifecycle lifecycle = null;
    private String type = null;
    public Object getData() {
        return (this.data);
    }
    public Lifecycle getLifecycle() {
        return (this.lifecycle);
    }
    public String getType() {
        return (this.type);
    }
}
再看下监听器接口LifecycleListener :
public interface LifecycleListener {
    //当监听器感兴趣的事情发生时 调用该方法
    public void lifecycleEvent(LifecycleEvent event);
}

监听器是怎么样注册自己感兴趣的事件呢?那就需要LifecycleSupport这个帮助类。

public final class LifecycleSupport {
    public LifecycleSupport(Lifecycle lifecycle) {
        super();
        this.lifecycle = lifecycle;
    }
    //引用一个实现了Lifecycle接口的Tomcat组件
    private Lifecycle lifecycle = null;
    //监听器数组
    private LifecycleListener listeners[] = new LifecycleListener[0];

    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 LifecycleListener[] findLifecycleListeners() {
        return listeners;
    }
    //事件触发
    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);
    }
    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;
        }
    }
}

来看下一个简单的Context是如何启动/停止它的子组件、子容器,绑定生命周期事件和监听器的呢。

public class SimpleContext implements Context, Pipeline, Lifecycle {
    //把SimpleContext自己注册给帮助类
    protected LifecycleSupport lifecycle = new LifecycleSupport(this);
    //委托帮助类处理监听器
    public void addLifecycleListener(LifecycleListener listener) {
        lifecycle.addLifecycleListener(listener);
    }
    public LifecycleListener[] findLifecycleListeners() {
        return null;
    }
    public void removeLifecycleListener(LifecycleListener listener) {
        lifecycle.removeLifecycleListener(listener);
    }
    public synchronized void start() throws LifecycleException {
        if (started) throw new LifecycleException("SimpleContext has already started");
        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
        started = true;
        try {
            if ((loader != null) && (loader instanceof Lifecycle))
                ((Lifecycle) loader).start();
            //启动子容器
            Container Children[] = findChildren();
            for (int i = 0; i < children.length; i++) {
                if (children[i] instanceof Lifecycle)
                    ((Lifecycle) children[i]).start();
            }
            //启动pipeline中的value(包括baseValue)
            if (pipeline instanceof Lifecycle)
                ((Lifecycle) pipeline).start();
            //绑定事件监听器
            lifecycle.firelifecycleEvent(START_EVENT, null);
        } catch (Exception e) {
            e.printStackTrace();
        } 
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
    }
    public void stop() throws LifecycleException {
        if (!started) throw new LifecycleException("SimpleContext has not been started"); 
        lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
        started = false;
        try {
            if (pipeline instanceof Lifecycle){
                ((Lifecycle) pipeline).stop();
            }
            Container children[] = findChildren();
            for (int i = 0; i < children.length; i++) {
                if (children[i] instanceof Lifecycle)
                    ((Lifecycle) children[i]).stop();
            }
            if ((loader != null) && (loader instanceof Lifecycle)) {
                ((Lifecycle) loader).stop();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
}

Lifecycle接口定义了一个组件的生命周期,并提供一个优雅的方式向组件推送事件。
另外通过Lifecycle接口,Tomcat可以"一键"启动/停止所有组件。

你可能感兴趣的:(tomcat)