上一節說到StandardService負責啟動其子組件:container和connector,不過注意,是有先後順序的,先啟動container,再啟動connector,這一節先來看看container。
在第二節(How Tomcat works — 二、tomcat啟動(1))中沒有介紹關於Pipeline和Vavle,因為前面側重的是整個架構,但是在初始化的時候就不得不說了。
Pipeline,就是一根管道,用來連接兩個容器,在一個容器流向下一個容器的時候使用。在tomcat中也是這個意思,很形象,Engine、Host等都是容器,在執行完上一個容器(比如Engine)的相關操作的時候要開始執行下一個容器(比如Host)的操作了,這個時候需要經過一根管道pipeline,那麼我們可以在管道中執行一個其他必要的操作,這個時候可以在管道上面添加Vavle(閥),一根管道pipeline上可以有多個閥門(也很形象)。每根管道都有一個默認的閥門。
在tomcat實現中有一個實現了Pipeline接口的類StandardPipeline——是每兩個容器之間的管道,每個容器都有一個默認的Valve實現StandardEnginevavle、StandardHostValve、StandardContextVavle、StandardWrapperVavle。
其實valve的作用和filter的作用類似。
StandardEngine作為整個容器的最頂層負責啟動其子組件——StandardHost,對,他就這一個作用。
這個方法被超類LifecycleBase.init方法調用,主要作用就是調用超類LifecycleMBeanBase.initInternal方法注冊MBean,並初始化一個startStopExecutor(ThreadPoolExecutor),後面用來使用線程啟動子容器。
這個方法的主要作用就是調用父類的方法Container.startInternal——主要的操作就在這個方法裡面:
protected synchronized void startInternal() throws LifecycleException { // Start our subordinate components, if any if ((loader != null) && (loader instanceof Lifecycle)) ((Lifecycle) loader).start(); logger = null; getLogger(); if ((manager != null) && (manager instanceof Lifecycle)) ((Lifecycle) manager).start(); if ((cluster != null) && (cluster instanceof Lifecycle)) ((Lifecycle) cluster).start(); Realm realm = getRealmInternal(); if ((realm != null) && (realm instanceof Lifecycle)) ((Lifecycle) realm).start(); if ((resources != null) && (resources instanceof Lifecycle)) ((Lifecycle) resources).start(); // Start our child containers, if any Container children[] = findChildren(); List<Future<Void>> results = new ArrayList<Future<Void>>(); for (int i = 0; i < children.length; i++) { results.add(startStopExecutor.submit(new StartChild(children[i]))); } boolean fail = false; for (Future<Void> result : results) { try { result.get(); } catch (Exception e) { log.error(sm.getString("containerBase.threadedStartFailed"), e); fail = true; } } if (fail) { throw new LifecycleException( sm.getString("containerBase.threadedStartFailed")); } // Start the Valves in our pipeline (including the basic), if any if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start(); setState(LifecycleState.STARTING); // Start our thread threadStart(); } View CodeStandardHost的作用和StandardEngine類似,都是初始化啟動子容器,不過這裡是StandardContext。啟動的方式也一樣,所以就不再詳述。
這個類才是重中之重,解析web.xml、部署webapp都在這兒實現。在StandardHost中調用StandardContext.start方法,執行的是超類LifecycleBase.start方法,主要進行了如下操作
在該方法中主要進行了MBean的注冊,再就是觸發了Lifecycle.AFTER_INITEVENT事件,ContextConfig是StandardContext的listener,在發生該事件的時候執行ContextConfig.init方法,在該方法中主要是構造一個能解析web.xml的digester。
由於LifecycleBase沒有實現該方法,所以就是直接調用StandardContext.startInternal,在StandardContext.startInternal方法中主要進行了如下操作:
container部分終於啟動完成了,不過還是有些部分略過了,比如StandardWrapper(這個還可以往深挖,不過也包含在StandardContext的啟動過程中)初始化和webapp的發布。到現在發現,這些啟動過程就是圍繞生命周期的這幾個方法展開: