《How Tomcat Works》讀書筆記(六)Lifecycle

Tomcat有不少組件,在Tomcat啓動的同時,這些組件也應該跟着啓動,在Tomcat要中止以前,這些組件須要有機會完成本身的收尾工做. java

以前提過servlet的生命週期,從上一節咱們知道一個Wrapper表明一個Servlet,一個Context能夠有不少個Wrapper.當一個Context要中止,它會調用它的Wrapper的stop方法,Wrapper會調用servlet的destory方法. apache

一個組件只需實現org.apache.catalina.Lifecycle就能夠管理本身的生命週期了。 數組

看一下Lifecycle的接口定義: app

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裏只有生命週期事件的名稱,來看下它的實現:  this

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這個幫助類。 spa

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是如何啓動/中止它的子組件、子容器,綁定生命週期事件和監聽器的呢。 rest

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能夠"一鍵"啓動/中止全部組件。 code

相關文章
相關標籤/搜索