Tomcat原始碼分析-初始化流程
主要類圖
Tomcat的Bootstrap類關聯的幾個主要類整理如下:
初始化入口類是Catalina,它的load()完成初始化所有類的過程,主類StandardServer類有兩個父類,它提供了生命週期的管理方法,同時也具有ManagedBean的功能。
進一步分析得到初始化過程中的時序圖。
初始化時序圖
start方法包括兩個步驟,load和start。load操作最終轉換為Catalina類的createStartDigester()和StandardServer的initInternal()方法;start最終轉化為StandardServer類的startInternal()。
load方法流程圖
load方法主要是建立一個Digester物件,然後呼叫其parse方法完成對server.xml檔案的解析。
流程圖如下:
createStartDigester方法主要是安裝server.xml檔案的組織形式,建立一系列的解析規則。
原始碼如下:(可以直觀感覺出這個組裝過程其實就是server.xml的內容)
protected Digester createStartDigester() {
long t1=System.currentTimeMillis();
// Initialize the digester
Digester digester = new Digester();
digester.setValidating(false);
digester.setRulesValidation(true);
HashMap<Class<?>, List<String>> fakeAttributes = new HashMap<>();
ArrayList<String> attrs = new ArrayList<>();
attrs.add("className");
fakeAttributes.put(Object.class, attrs);
digester.setFakeAttributes(fakeAttributes);
digester.setUseContextClassLoader(true );
// Configure the actions we will be using
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");
digester.addSetProperties("Server");
digester.addSetNext("Server",
"setServer",
"org.apache.catalina.Server");
digester.addObjectCreate("Server/GlobalNamingResources",
"org.apache.catalina.deploy.NamingResourcesImpl");
digester.addSetProperties("Server/GlobalNamingResources");
digester.addSetNext("Server/GlobalNamingResources",
"setGlobalNamingResources",
"org.apache.catalina.deploy.NamingResourcesImpl");
digester.addObjectCreate("Server/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Listener");
digester.addSetNext("Server/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
digester.addObjectCreate("Server/Service",
"org.apache.catalina.core.StandardService",
"className");
digester.addSetProperties("Server/Service");
digester.addSetNext("Server/Service",
"addService",
"org.apache.catalina.Service");
digester.addObjectCreate("Server/Service/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Listener");
digester.addSetNext("Server/Service/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
//Executor
digester.addObjectCreate("Server/Service/Executor",
"org.apache.catalina.core.StandardThreadExecutor",
"className");
digester.addSetProperties("Server/Service/Executor");
digester.addSetNext("Server/Service/Executor",
"addExecutor",
"org.apache.catalina.Executor");
digester.addRule("Server/Service/Connector",
new ConnectorCreateRule());
digester.addRule("Server/Service/Connector",
new SetAllPropertiesRule(new String[]{"executor"}));
digester.addSetNext("Server/Service/Connector",
"addConnector",
"org.apache.catalina.connector.Connector");
digester.addObjectCreate("Server/Service/Connector/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Connector/Listener");
digester.addSetNext("Server/Service/Connector/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
// Add RuleSets for nested elements
digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
digester.addRuleSet(new EngineRuleSet("Server/Service/"));
digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));
// When the 'engine' is found, set the parentClassLoader.
digester.addRule("Server/Service/Engine",
new SetParentClassLoaderRule(parentClassLoader));
addClusterRuleSet(digester, "Server/Service/Engine/Cluster/");
long t2=System.currentTimeMillis();
if (log.isDebugEnabled()) {
log.debug("Digester for server.xml created " + ( t2-t1 ));
}
return (digester);
}
最終執行過程中,生成的Digester例項中的規則達到了200多種,我們可以關注第一節中的主要類圖的規則即可。
Digester類
Catalina類的createStartDigester方法返回的是一個Digester類的例項,它的作用就是根據設定的一系列規則,解析config/server.xml檔案,組織建立第一張類圖中所有具有相互依賴關係的物件,類的功能說明如下:
Digester processes an XML input stream by matching a
series of element nesting patterns to execute Rules that have been added
prior to the start of parsing.
Digester類圖分析如下:
根據這個類的繼承體系及它的成員變數的組成,很容易知道它就是以SAX方式解析xml檔案的一個類。DefaultHandler和DefaultHandler2類所有方法實現都是空方法,Digester類繼承基礎實現型別,並重新了幾個重要解析方法。
startDocument()
startElement()
characters()
endDocument()
endElement()
程式碼啟示錄
這個初始化流程還是挺複雜的,逐一梳理類圖結構就費了一番功夫,能想明白這個初始化流程。第一張類圖,裡面涉及了一個設計模式就是模版方法的模式,此外就是Digester類組裝Java物件的過程。