Tomcat源码分析-初始化流程

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wojiushiwo945you/article/details/72884510

主要类图

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对象的过程。

展开阅读全文
博主设置当前文章不允许评论。

没有更多推荐了,返回首页