Catalina.createDigester方法詳細理解

 這個方法主要設置(這個方法很重要,貴在理解,雖然還沒學過設計模式。。)java

一、遇到<server>標籤時建立StandardServer實例web

   設置StandardServer類內部的相關屬性apache

   並調用Catalina.setServer()方法設置serverwindows

二、遇到<Server>標籤的子標籤<Listener>==》對應匹配模式"Server/Listener"時設計模式

  建立Listener實例,建立類名經過<Listener className=要建立的全類名(包名+類名)>獲取屬性className的值進行建立。tomcat

  調用StandardServer的addLifecycleListener()爲server添加監聽器app

三、<Service>標籤時即匹配模式爲:"Server/Service"建立StandardService實例,放入Stack棧中,調用addSetProperties方法爲StandardService設置相關屬性eclipse

  

digester.addSetNext("Server/Service", "addService", "org.apache.catalina.Service");

調用Service的parent=stack.peek(1)即Server對象的addService方法爲與Server關聯。ide

四、同2同樣爲Service設置監聽器post

五、<executor>標籤時即匹配模式:"Server/Service/Executor" 生成StandardThreadExecutor實例,

   設置StandardThreadExecutor的屬性

  調用其父類Service的addExecutor方法與Service關聯

六、調用addRule方法如上同樣,

pattern:"Server/Service/Connector"==>建立Connector實例,設置屬性,調用StandardService.addConnector()。爲Connector設置監聽器

七、調用addRuleSet()方法

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/"));

跟6同樣

、、設置Engine

EngineRuleSet(String prefix)當遇到模式爲prefix + "Engine"即"Server/Service/Engine"會在EngineRuleSet.addRuleInstances()內部調用

addObjectCreate、addSetProperties、addRule這三個方法建立StandardEngine實例,設置屬性,調用Service。setContainer()方法。

建立SimpleTcpCluster實例調用Engine.setCluster()方法

給Engine添加監聽器,

建立realm對象實例,調用對應方法與Engine關聯。

建立AccessLogValve日誌對象(將日誌輸出到。txt文件),設置屬性,與engine關聯。

、、設置host

建立StandardHost,設置屬性,設置監聽器:HostConfig

調用Container。addChild()在這裏Container即與Engine相關聯

、、設置context

建立StandardContext,設置屬性,設置監聽器:ContextConfig

調用Container。addChild()在這裏Container即與Host相關聯

建立WebappLoader,與StandardContext關聯

建立StandardManager,與StandardContext關聯

建立store存儲類,與StandardContext關聯

建立StandardSessionIdGenerator,與StandardManager關聯

建立ApplicationParameter,與StandardContext關聯

建立realm對象實例,與StandardContext關聯

建立StandardRoot,與StandardContext關聯

  context==》WebResourceRoot==StandardRoot設置

  org.apache.catalina.webresources.StandardRoot提供各類resources實現類

  建立WebResourceSet,與StandardRoot關聯

  (WebResourceSet的實現類有WarResourceSet、JarResourceSet、JarWarResourceSet、DirResourceSet、FileResourceSet等)

  主要設置StandardRoot的preResources、jarResources、postResources這三個變量的實例

建立ContextResourceLink,與StandardContext關聯

建立AccessLogValve,與StandardContext關聯

建立StandardJarScanner,與StandardContext關聯

  建立StandardJarScanFilter,與StandardJarScanner關聯

建立LegacyCookieProcessor與StandardContext關聯

 Note:上面已經說明完的具體對象被建立的整個過程,下面是對Digester的一些方法的理解。能夠忽略!


 

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);

    }

 

addObjectCreate()//Add an "object create" rule for the specified parameters.增長對象建立規則.遇到起始標籤的元素,初始化一個實例對象入棧

addSetProperties()//Add a "set properties" rule for the specified parameters.增長設置屬性規則.遇到某個屬性名,使用setter來賦值

digester.addSetProperties("Server");

對應標籤<Server port="8005" shutdown="SHUTDOWN">

遇到匹配模式爲:Server。addSetProperties方法會反射調用StandardServer對象的setPort(int) 和setShutdown(String)兩個方法設置屬性

 
Digester.addSetNext( String pattern, String methodName, String paramType)

 //Add a "set next" rule for the specified parameters.增長set next規則.遇到下一標籤時的動做

即反射調用方法名爲methodName的方法。

digester.addSetNext("Server", "setServer", "org.apache.catalina.Server");
當遇到<Server>標籤的下一標籤時被調用

addSetNext方法會調用SetNextRule.end()方法會調用這個當前top棧頂對象的parent父對象(棧頂對象的下一個元素)的setServer()方法

當StandardServer對象入棧後,棧中已經存在Catalina對象===>在Catalina.load()方法中設置了

因此StandardServer的parent父對象是Catalina,即調用Catalina.setServer()方法設置server屬性。

 

addRule:調用rule的begin 、body、end、finish方法來解析xml,入棧和出棧給對象賦值

addRuleSet:調用addRuleInstances來解析xml標籤

 


 

addObjectCreate(pattern ,className ,attributeName

一、

Add an "object create" rule for the specified parameters爲指定的參數增長一個對象建立規則.

Parameters:
pattern Element matching pattern元素匹配模式
className Default Java class name to be created要建立的java類的名字
attributeName Attribute name that optionally overrides the default Java class name to be created屬性名稱能夠覆蓋要建立的默認Java類名稱
獲取xml文件中attributes屬性名爲:className所對應的值替換第二個參數
ObjectCreateRule.java類的begin(String namespace, String name, Attributes attributes)方法,
這個方法將經過類名加載Class而後調用class.newInstance()生成類實例,最後放入digest的對象棧頂digester.push(instance);
String realClassName = className; if (attributeName != null) { String value = attributes.getValue(attributeName); if (value != null) { realClassName = value; } }

 

Digester.addObjectCreate(String pattern, String className, String attributeName)

 這個addObjectCreate()方法又調用addRule()方法

二、

Register a new Rule matching the specified pattern. This method sets the Digester property on the rule.

Parameters:
pattern Element matching pattern
rule Rule to be registered這裏的rule使用的是ObjectCreateRule
Digester.addRule(String pattern, Rule rule)
addRule(pattern, new ObjectCreateRule(className, attributeName));
public void addRule(String pattern, Rule rule) {

        rule.setDigester(this);設置digester,將保存建立的對象的實例
        getRules().add(pattern, rule);這裏將會返回Rules接口的實現類。而後再調用Rules.add()來添加Rule實例

    }
Note:Rules:是一個接口public interface Rules
        公共接口定義規則實例的集合(和相應的匹配模式)以及匹配策略的實現,
        該策略選擇與解析期間發現的嵌套元素的特定模式匹配的規則。
   Rule:是一個抽象類public abstract class Rule

 

 ObjectCreateRule類的解釋

Rule implementation that creates a new object and pushes it onto the object stack. When the element is complete, the object will be popped

Rule實現類,建立一個新對象並將其推送到對象堆棧上。當元素完成時,對象將被彈出

三、RuleBase.add(pattern, rule)

public void add(String pattern, Rule rule) {
        // to help users who accidently add '/' to the end of their patterns
        int patternLength = pattern.length();
        if (patternLength>1 && pattern.endsWith("/")) {
            pattern = pattern.substring(0, patternLength-1);
        }


        List<Rule> list = cache.get(pattern);
        if (list == null) {
            list = new ArrayList<>();
            cache.put(pattern, list);
        }
        list.add(rule);
        rules.add(rule);
        if (this.digester != null) {
            rule.setDigester(this.digester);
        }
        if (this.namespaceURI != null) {
            rule.setNamespaceURI(this.namespaceURI);
        }

    }

上面方法用用HashMap<String, List<Rule>>類型變量cache存放pattern和Rule集合,用rules集合存放新加入的規則rules.add(rule)

Digester.addSetProperties(String pattern)
這個方法跟addObjectCreate方法調用類似順序以下
1addRule(pattern, new SetPropertiesRule());
2getRules().add(pattern, rule);
3RulesBase.add(pattern, rule)
Digester.addSetNext(String pattern, String methodName, String paramType)
1addRule(pattern, new SetNextRule(methodName, paramType));
2getRules().add(pattern, rule);
3RulesBase.add(pattern, rule)

 注:

只有當遇到改元素的結束標籤時纔會將改標籤表明的對象實例彈出棧。

相關文章
相關標籤/搜索