1.摘要
對於獨立運行的應用程序來說,都有一個入口,以便啓動應用程序。Java應用程序的入口是類的main方法,在這裏你可以初始化應用的上下文環境,然後創建應用組件並提供服務。對於簡單的應用程序,可以直接將啓動代碼放在main方法中,但是,對於複雜的,或者可擴展的應用來說,這樣做是不負責任的,也是不優雅的。那麼,怎麼做纔是負責任的,優雅的?下面我們看看Tomcat是如何啓動的,分析一下它的啓動框架。希望從中能找到答案。
2.Tomcat啓動框架
默認的情況下,在命令行下啓動Tomcat,程序的入口是org.apache.catalina.startup.Bootstrap類的main方法,Bootstrap是一個final類,不允許擴展。下面看看main方法,
publicstaticvoid main(String args[]) {
if (daemon == null) {
daemon = new Bootstrap();
try {
daemon.init();
} catch (Throwable t) {
t.printStackTrace();
return;
}
}
try {
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
}
if (command.equals("startd")) {
args[0] = "start";
daemon.load(args);
daemon.start();
} elseif (command.equals("stopd")) {
args[0] = "stop";
daemon.stop();
} elseif (command.equals("start")) {
daemon.setAwait(true);
daemon.load(args);
daemon.start();
} elseif (command.equals("stop")) {
daemon.stopServer(args);
} else {
log.warn("Bootstrap: command \"" + command + "\" does not exist.");
}
} catch (Throwable t) {
t.printStackTrace();
}
}
由代碼可知,main方法很簡單,就做2件事,一.實例化和初始化Bootstrap,並緩存起來,二.處理命令行參數,根據參數調用不同的操作,此之謂引導。看一下序列圖更加清晰:
2.1引導過程
一般來說,在使用一個對象之前,要先初始化好這個對象的狀態(就是屬性的值),而Bootstrap的初始化也無非幹了這些事。
首先初始化屬性commonLoader,catalinaLoader,sharedLoader的值,在初始化的過程中先設置了環境變量${catalina.home}和${catalina.base},然後讀取配置文件,創建ClassLoader並賦值給屬性字段。
接着使用catalinaLoader加載org.apache.catalina.startup.Catalina類並實例化一個對象,並將該對象設置到屬性catalinaDaemon中。
當Bootstrap對象初始化完了,就可以接受命令並引導服務了。不同的命令對應不同的Bootstrap動作,而Bootstrap動作委託給Catalina對象來處理。
2.2Catalina
我們知道,Tomcat是面向組件設計的典範,而且組件的裝配是可配置的,那麼在Tomcat實例啓動之前,必須有一個地方來裝配這些個組件。Catalina類正好擔此重任。Catalina主要負責Tomcat的裝配,並在Bootstrap的引導下操作Tomcat實例。
當Bootstrap接到“start”命令後,會引導Catalina對象的load動作裝配一個新的Server實例,接着Bootstrap引導Catalina對象啓動Server實例。由此可以看出,Catalina是Tomcat實例的裝配工廠和引線。