1. 程式人生 > >Tomcat原始碼分析-初始化流程

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物件的過程。