Tomcat中组件的生命周期管理(三)
本文主要目的是自定義舉例分析Catalina內部生命周期管理的運作方式以及拿內部具體源碼來具體分析
假設我們有一臺電腦由主機(我們用cpu表示)和顯示器構成,那么我們要運用上篇文章學到的內容,來管理整個電腦的啟動和關閉,先看我們對類的定義。
在本例中我們對Lifecycle類進行了部分刪減,只保留了關于start和stop的相關事件。
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相關方法。
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 + " 準備啟動");fireLifecycleEvent(Lifecycle.BEFORE_START_EVENT, null);System.out.println(name + " 正在啟動");fireLifecycleEvent(Lifecycle.START_EVENT, null);startInternal();System.out.println(name + " 啟動完畢");fireLifecycleEvent(Lifecycle.AFTER_START_EVENT, null);}protected abstract void stopInternal() throws LifecycleException;@Overridepublic void stop() throws LifecycleException {System.out.println(name + " 準備關閉");fireLifecycleEvent(Lifecycle.BEFORE_STOP_EVENT, null);System.out.println(name + " 正在關閉");stopInternal();fireLifecycleEvent(Lifecycle.STOP_EVENT, null);System.out.println(name + " 關閉完畢");fireLifecycleEvent(Lifecycle.AFTER_STOP_EVENT, null);}}
電腦組成部件 CPU定義
CPU
public class CPU extends LifeCycleBase {@Overridepublic void startInternal() throws LifecycleException {System.out.println(super.name + "在啟動過程中 負載達到了100%!");}@Overridepublic void stopInternal() throws LifecycleException {System.out.println(name + "在關閉過程中 負載下降到了1%!");}public CPU(String name) {super.name = name;}}
電腦組成部件 Monitor定義
Monitor
public class Monitor extends LifeCycleBase {@Overridepublic void startInternal() throws LifecycleException {System.out.println(name + "在啟動過程中 屏幕 很亮!");}@Overridepublic void stopInternal() throws LifecycleException {System.out.println(name + "在關閉過程中 屏幕漸漸暗了下去");}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 + "在啟動過程中 需要先啟動子組件");if (cpu != null) {((Lifecycle) cpu).start();}if (monitor != null) {((Lifecycle) monitor).start();}}@Overridepublic void stopInternal() throws LifecycleException {System.out.println(name + "在關閉過程中 需要先關閉子組件");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;}}
運行類代碼
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("已經監聽到 cpu正在準備啟動");}}});monitor.addLifecycleListener(new LifecycleListener() {@Overridepublic void lifecycleEvent(LifecycleEvent event) {if (event.getType().equals(Lifecycle.AFTER_STOP_EVENT)) {System.out.println("已經監聽到顯示器 已經停止");}}});//啟動computer.start();System.out.println("------------------------------------------");computer.stop();}}運行結果
電腦 準備啟動 電腦 正在啟動 電腦在啟動過程中 需要先啟動子組件 CPU 準備啟動 已經監聽到 cpu正在準備啟動 CPU 正在啟動 CPU在啟動過程中 負載達到了100%! CPU 啟動完畢 顯示器 準備啟動 顯示器 正在啟動 顯示器在啟動過程中 屏幕 很亮! 顯示器 啟動完畢 電腦 啟動完畢 ------------------------------------------ 電腦 準備關閉 電腦 正在關閉 電腦在關閉過程中 需要先關閉子組件 CPU 準備關閉 CPU 正在關閉 CPU在關閉過程中 負載下降到了1%! CPU 關閉完畢 顯示器 準備關閉 顯示器 正在關閉 顯示器在關閉過程中 屏幕漸漸暗了下去 顯示器 關閉完畢 已經監聽到顯示器 已經停止 電腦 關閉完畢從源碼可以看到每個組件的啟動都會調用父類的start()方法,而start()方法又會調用本類的startInternal()方法,stop方法類似。在父類的start()方法定義了一些組件共性的動作,而在startInternal()方法中定義了組件自己的特殊動作。并且每個組件都可以自行添加自己的監聽器。從運行的代碼可以看到,只要設置好每個組件的關系就可以統一管理每個組件的啟動關閉了。Catalina中的生命周期管理的模式大概就是這樣,下面我們找個具體的類來分析。
我們主要分析start()方法相關,其他類似init(),stop(),destroy()方法都是類似的。我們從前面的文章可以知道Tomcat啟動的時候是調用了Bootstrap類的main()方法,而main()方法中最后調用了Catalina類的start()方法,我們查看Catalina類的start()方法,其中
getServer().start();這一步又調用了StandardServer類的start()方法,從這里就Catalina是最頂層組件,下面所有的組件都開始需要進行生命周期管理了。所以查看StandardServer類的定義
public final class StandardServer extends LifecycleMBeanBase implements Server再查看LifecycleMBeanBase類的定義
public abstract class LifecycleMBeanBase extends LifecycleBase implements MBeanRegistration我們在這里就看到了上文介紹的關鍵類LifecycleBase類。之所以有個LifecycleMBeanBase類橫跨在這里主要是因為Tomcat要將組件納入JMX管理,所以用這個類來實現,這個不再本文的講解范圍之內,所以暫時不討論,可以當作組件直接繼承LifecycleBase類。
既然StandardServer類直接繼承了LifecycleBase類,那么Catalina調用StandardServer類的start()方法就是調用LifecycleBase類的start()方法(這樣的前提是StandardServer,LifecycleMBeanBase類中沒有start()方法,實際上這2個類的確沒有實現start()方法)。上篇文章已經分析過LifecycleBase類的start()方法具體源碼,因為start()方法中會調用子類的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();}} }可以看到思路非常簡單
- 觸發某個事件(針對自己內部所有監聽器)
- 更改自己組件狀態
- 調用子組件的start()方法,包括globalNamingResources和StandardService。
至于這些子組件什么時候設置到本類中的,讀者可以自行發現。
我們可以繼續往下再看一點,既然調用了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);}}} }雖然代碼看起來很多,但是按照上面的思路來看的話,還是那幾步。
- 更改當前組件狀態
- 調用自己子組件的start()方法包含container,connector
看到這里我們就不繼續往下看了,因為之前啟動的文章都已經分析過了,是不是覺得看到這里對啟動的流程理解又上了一層。其實自己看看每個組件的startInternal()方法都是在啟動自己的子組件,而組件的子組件可以從哪里找到呢?可以看看Digster那篇文章,疑惑看看server.xml也許會有恍然大悟的感覺,至于具體代碼去哪里找,讀者可以自行挖掘。
寫到這里只能感慨Tomcat設計者設計的精巧,代碼的簡潔,簡直完美!
轉載于:https://www.cnblogs.com/coldridgeValley/p/5816417.html
總結
以上是生活随笔為你收集整理的Tomcat中组件的生命周期管理(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: information_schema.r
- 下一篇: MVC5中EF6 Code First启