Tomcat中组件的生命周期管理(三)
本文主要目的是自定義舉例分析Catalina內(nèi)部生命周期管理的運(yùn)作方式以及拿內(nèi)部具體源碼來具體分析
假設(shè)我們有一臺(tái)電腦由主機(jī)(我們用cpu表示)和顯示器構(gòu)成,那么我們要運(yùn)用上篇文章學(xué)到的內(nèi)容,來管理整個(gè)電腦的啟動(dòng)和關(guān)閉,先看我們對(duì)類的定義。
在本例中我們對(duì)Lifecycle類進(jìn)行了部分刪減,只保留了關(guān)于start和stop的相關(guān)事件。
Lifecycle
public interface Lifecycle {// ----------------------------------------------------- Manifest Constantspublic 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 Methodspublic void addLifecycleListener(LifecycleListener listener);public LifecycleListener[] findLifecycleListeners();public void removeLifecycleListener(LifecycleListener listener);public void start() throws LifecycleException;public void stop() throws LifecycleException;}
同樣LifecycleBase類也只保留了start,stop相關(guān)方法。
LifecycleBase
public abstract class LifeCycleBase implements Lifecycle {private LifecycleSupport support = new LifecycleSupport(this);//組件名稱public String name;@Overridepublic void addLifecycleListener(LifecycleListener listener) {support.addLifecycleListener(listener);}@Overridepublic LifecycleListener[] findLifecycleListeners() {return support.findLifecycleListeners();}@Overridepublic void removeLifecycleListener(LifecycleListener listener) {support.removeLifecycleListener(listener);}protected void fireLifecycleEvent(String type, Object data) {support.fireLifecycleEvent(type, data);}protected abstract void startInternal() throws LifecycleException;@Overridepublic void start() throws LifecycleException {System.out.println(name + " 準(zhǔn)備啟動(dòng)");fireLifecycleEvent(Lifecycle.BEFORE_START_EVENT, null);System.out.println(name + " 正在啟動(dòng)");fireLifecycleEvent(Lifecycle.START_EVENT, null);startInternal();System.out.println(name + " 啟動(dòng)完畢");fireLifecycleEvent(Lifecycle.AFTER_START_EVENT, null);}protected abstract void stopInternal() throws LifecycleException;@Overridepublic void stop() throws LifecycleException {System.out.println(name + " 準(zhǔn)備關(guān)閉");fireLifecycleEvent(Lifecycle.BEFORE_STOP_EVENT, null);System.out.println(name + " 正在關(guān)閉");stopInternal();fireLifecycleEvent(Lifecycle.STOP_EVENT, null);System.out.println(name + " 關(guān)閉完畢");fireLifecycleEvent(Lifecycle.AFTER_STOP_EVENT, null);}}
電腦組成部件 CPU定義
CPU
public class CPU extends LifeCycleBase {@Overridepublic void startInternal() throws LifecycleException {System.out.println(super.name + "在啟動(dòng)過程中 負(fù)載達(dá)到了100%!");}@Overridepublic void stopInternal() throws LifecycleException {System.out.println(name + "在關(guān)閉過程中 負(fù)載下降到了1%!");}public CPU(String name) {super.name = name;}}
電腦組成部件 Monitor定義
Monitor
public class Monitor extends LifeCycleBase {@Overridepublic void startInternal() throws LifecycleException {System.out.println(name + "在啟動(dòng)過程中 屏幕 很亮!");}@Overridepublic void stopInternal() throws LifecycleException {System.out.println(name + "在關(guān)閉過程中 屏幕漸漸暗了下去");}public Monitor(String name) {super.name = name;}}
電腦類的定義
Computer
public class Computer extends LifeCycleBase {private CPU cpu ;private Monitor monitor;@Overridepublic void startInternal() throws LifecycleException {System.out.println(name + "在啟動(dòng)過程中 需要先啟動(dòng)子組件");if (cpu != null) {((Lifecycle) cpu).start();}if (monitor != null) {((Lifecycle) monitor).start();}}@Overridepublic void stopInternal() throws LifecycleException {System.out.println(name + "在關(guān)閉過程中 需要先關(guān)閉子組件");if (cpu != null) {((Lifecycle) cpu).stop();}if (monitor != null) {((Lifecycle) monitor).stop();}}public Computer(String name) {super.name = name;}public void setCpu(CPU cpu) {this.cpu = cpu;}public void setMonitor(Monitor monitor) {this.monitor = monitor;}}
運(yùn)行類代碼
public class MainClass {public static void main(String[] args) throws Exception {Computer computer = new Computer("電腦");CPU cpu = new CPU("CPU");Monitor monitor = new Monitor("顯示器");computer.setCpu(cpu);computer.setMonitor(monitor);cpu.addLifecycleListener(new LifecycleListener() {@Overridepublic void lifecycleEvent(LifecycleEvent event) {if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {System.out.println("已經(jīng)監(jiān)聽到 cpu正在準(zhǔn)備啟動(dòng)");}}});monitor.addLifecycleListener(new LifecycleListener() {@Overridepublic void lifecycleEvent(LifecycleEvent event) {if (event.getType().equals(Lifecycle.AFTER_STOP_EVENT)) {System.out.println("已經(jīng)監(jiān)聽到顯示器 已經(jīng)停止");}}});//啟動(dòng)computer.start();System.out.println("------------------------------------------");computer.stop();}}運(yùn)行結(jié)果
電腦 準(zhǔn)備啟動(dòng) 電腦 正在啟動(dòng) 電腦在啟動(dòng)過程中 需要先啟動(dòng)子組件 CPU 準(zhǔn)備啟動(dòng) 已經(jīng)監(jiān)聽到 cpu正在準(zhǔn)備啟動(dòng) CPU 正在啟動(dòng) CPU在啟動(dòng)過程中 負(fù)載達(dá)到了100%! CPU 啟動(dòng)完畢 顯示器 準(zhǔn)備啟動(dòng) 顯示器 正在啟動(dòng) 顯示器在啟動(dòng)過程中 屏幕 很亮! 顯示器 啟動(dòng)完畢 電腦 啟動(dòng)完畢 ------------------------------------------ 電腦 準(zhǔn)備關(guān)閉 電腦 正在關(guān)閉 電腦在關(guān)閉過程中 需要先關(guān)閉子組件 CPU 準(zhǔn)備關(guān)閉 CPU 正在關(guān)閉 CPU在關(guān)閉過程中 負(fù)載下降到了1%! CPU 關(guān)閉完畢 顯示器 準(zhǔn)備關(guān)閉 顯示器 正在關(guān)閉 顯示器在關(guān)閉過程中 屏幕漸漸暗了下去 顯示器 關(guān)閉完畢 已經(jīng)監(jiān)聽到顯示器 已經(jīng)停止 電腦 關(guān)閉完畢從源碼可以看到每個(gè)組件的啟動(dòng)都會(huì)調(diào)用父類的start()方法,而start()方法又會(huì)調(diào)用本類的startInternal()方法,stop方法類似。在父類的start()方法定義了一些組件共性的動(dòng)作,而在startInternal()方法中定義了組件自己的特殊動(dòng)作。并且每個(gè)組件都可以自行添加自己的監(jiān)聽器。從運(yùn)行的代碼可以看到,只要設(shè)置好每個(gè)組件的關(guān)系就可以統(tǒng)一管理每個(gè)組件的啟動(dòng)關(guān)閉了。Catalina中的生命周期管理的模式大概就是這樣,下面我們找個(gè)具體的類來分析。
我們主要分析start()方法相關(guān),其他類似init(),stop(),destroy()方法都是類似的。我們從前面的文章可以知道Tomcat啟動(dòng)的時(shí)候是調(diào)用了Bootstrap類的main()方法,而main()方法中最后調(diào)用了Catalina類的start()方法,我們查看Catalina類的start()方法,其中
getServer().start();這一步又調(diào)用了StandardServer類的start()方法,從這里就Catalina是最頂層組件,下面所有的組件都開始需要進(jìn)行生命周期管理了。所以查看StandardServer類的定義
public final class StandardServer extends LifecycleMBeanBase implements Server再查看LifecycleMBeanBase類的定義
public abstract class LifecycleMBeanBase extends LifecycleBase implements MBeanRegistration我們?cè)谶@里就看到了上文介紹的關(guān)鍵類LifecycleBase類。之所以有個(gè)LifecycleMBeanBase類橫跨在這里主要是因?yàn)門omcat要將組件納入JMX管理,所以用這個(gè)類來實(shí)現(xiàn),這個(gè)不再本文的講解范圍之內(nèi),所以暫時(shí)不討論,可以當(dāng)作組件直接繼承LifecycleBase類。
既然StandardServer類直接繼承了LifecycleBase類,那么Catalina調(diào)用StandardServer類的start()方法就是調(diào)用LifecycleBase類的start()方法(這樣的前提是StandardServer,LifecycleMBeanBase類中沒有start()方法,實(shí)際上這2個(gè)類的確沒有實(shí)現(xiàn)start()方法)。上篇文章已經(jīng)分析過LifecycleBase類的start()方法具體源碼,因?yàn)閟tart()方法中會(huì)調(diào)用子類的startInternal()方法,所以可以直接查看StandardServer類的startInternal()方法。
@Override protected void startInternal() throws LifecycleException {fireLifecycleEvent(CONFIGURE_START_EVENT, null);setState(LifecycleState.STARTING);globalNamingResources.start();// Start our defined Servicessynchronized (servicesLock) {for (int i = 0; i < services.length; i++) {services[i].start();}} }可以看到思路非常簡(jiǎn)單
- 觸發(fā)某個(gè)事件(針對(duì)自己內(nèi)部所有監(jiān)聽器)
- 更改自己組件狀態(tài)
- 調(diào)用子組件的start()方法,包括globalNamingResources和StandardService。
至于這些子組件什么時(shí)候設(shè)置到本類中的,讀者可以自行發(fā)現(xiàn)。
我們可以繼續(xù)往下再看一點(diǎn),既然調(diào)用了StandardService的start()方法,查看StandardService類的定義。
public class StandardService extends LifecycleMBeanBase implements Service類似StandardServer,那么直接查看其startInternal()方法。
@Override protected void startInternal() throws LifecycleException {if(log.isInfoEnabled())log.info(sm.getString("standardService.start.name", this.name));setState(LifecycleState.STARTING);// Start our defined Container firstif (container != null) {synchronized (container) {container.start();}}synchronized (executors) {for (Executor executor: executors) {executor.start();}}// Start our defined Connectors secondsynchronized (connectorsLock) {for (Connector connector: connectors) {try {// If it has already failed, don't try and start itif (connector.getState() != LifecycleState.FAILED) {connector.start();}} catch (Exception e) {log.error(sm.getString("standardService.connector.startFailed",connector), e);}}} }雖然代碼看起來很多,但是按照上面的思路來看的話,還是那幾步。
- 更改當(dāng)前組件狀態(tài)
- 調(diào)用自己子組件的start()方法包含container,connector
看到這里我們就不繼續(xù)往下看了,因?yàn)橹皢?dòng)的文章都已經(jīng)分析過了,是不是覺得看到這里對(duì)啟動(dòng)的流程理解又上了一層。其實(shí)自己看看每個(gè)組件的startInternal()方法都是在啟動(dòng)自己的子組件,而組件的子組件可以從哪里找到呢?可以看看Digster那篇文章,疑惑看看server.xml也許會(huì)有恍然大悟的感覺,至于具體代碼去哪里找,讀者可以自行挖掘。
寫到這里只能感慨Tomcat設(shè)計(jì)者設(shè)計(jì)的精巧,代碼的簡(jiǎn)潔,簡(jiǎn)直完美!
轉(zhuǎn)載于:https://www.cnblogs.com/coldridgeValley/p/5816417.html
總結(jié)
以上是生活随笔為你收集整理的Tomcat中组件的生命周期管理(三)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: information_schema.r
- 下一篇: 【Unity3D】Tags和Layers