Tomcat 源码分析-启动分析(3)

38 篇文章 0 订阅
27 篇文章 0 订阅

Tomcat 源码分析-启动分析(3)

Catalina对象的load、start方法与Digester解析器

前边说道,Bootstrap的main方法最后调用了 org.apache.catalina.startup.Catalina 的 load 和 start 两个方法 。

总的概括的操作内容:

  • 首先,load方法:解析了server.xml文件,并生成了对应的server等对象并初始化。
  • 然后,start方法调用了解析初始化出来的server.start方法。【具体类为:StandardServer】

接下来,具体看一下这两个方法的东东吧。。

Catalina.load() 方法分析

load的部分源码 【因为有很多判断的代码,就删减了】

代码主要功能:初始化xml加载器Digester,配置其各种解析规则。然后将类本身入栈,并执行parse解析server.xml文件流,生产各种对应的实例类,并关联到类本身的server。

最后在初始化解析生产的server的init初始化方法。

public void load() {
        initDirs();//初始化文件目录
        initNaming();//初始化命名空间

        // Create and execute our Digester  : 这个是一个SAX模式解析xml的类。
        Digester digester = createStartDigester();
        /*server.xml的资源流*/
        InputSource inputSource = null;
        InputStream inputStream = null;
        File file = null;
    
   	 	inputSource.setByteStream(inputStream);
       	 //将当前对象压入栈。保存一个到 Digester 生成的一系列对象直接的引用,方便后续使用
       	 digester.push(this);
       	 //parse 方法解析 xml,生成相应的对象
       	 digester.parse(inputSource);
        getServer().setCatalina(this);

        // Start the new server  这里是就是:StandardServer.init()
        getServer().init();
    }

这里主要就是进行解析xml的了,核心的地方在Digester类的创建,它是进行解析并生成对应的server的处理类。

这里load最后调用的方法是getServer().init();【这里就是StandardServer类】

分析Digester类的操作

这里先来分析一下,代码中提到的Digester类,用来解析加载xml配置文件的,并且创建相应的Server服务的。

下面是createStartDigester()方法,主要的功能是:创建和配置Digester解析器。

 /**
     * Create and configure the Digester we will be using for startup.
     */
    protected Digester createStartDigester() {
        long t1=System.currentTimeMillis();
        // Initialize the digester
        Digester digester = new Digester();
        // 设置为false表示解析xml时不需要进行DTD的规则校验
        digester.setValidating(false);
        // 是否进行节点设置规则校验,如果xml中相应节点没有设置解析规则会在控制台显示提示信息
        digester.setRulesValidation(true);
        // 将xml节点中的className作为假属性,不必调用默认的setter方法(一般的节点属性在解析时将会以属性值作为入参调用该节点相应对象的setter方法,
        // 而className属性的作用是提示解析器用该属性的值来实例化对象)
        Map<Class<?>, List<String>> fakeAttributes = new HashMap<Class<?>, List<String>>();
        List<String> objectAttrs = new ArrayList<String>();
        objectAttrs.add("className");
        fakeAttributes.put(Object.class, objectAttrs);
        // Ignore attribute added by Eclipse for its internal tracking
        List<String> contextAttrs = new ArrayList<String>();
        contextAttrs.add("source");
        fakeAttributes.put(StandardContext.class, contextAttrs);
        digester.setFakeAttributes(fakeAttributes);
        digester.setUseContextClassLoader(true);

        // Configure the actions we will be using
        // addObjectCreate方法的意思是碰到xml文件中的Server节点则创建一个MyStandardServer对象
        digester.addObjectCreate("Server",
                                 "org.apache.catalina.core.StandardServer",
                                 "className");
        // 根据Server节点中的属性信息调用相应属性的setter方法,以上面的xml文件为例则会调用setPort、setShutdown方法,入参分别是8005、SHUTDOWN
        digester.addSetProperties("Server");
        // 将Server节点对应的对象作为入参调用栈顶对象的setServer方法,这里的栈顶对象即下面的digester.push方法所设置的当前类的对象this,就是说调用Catalina类的setServer方法
        digester.addSetNext("Server",
                            "setServer",
                            "org.apache.catalina.Server");

                            "org.apache.catalina.deploy.NamingResources");

        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");
。。。
        // Add RuleSets for nested elements 为嵌套元素添加规则集
        digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
。。。
        return (digester);
    }

这里一堆操作之后,初始化好digester的解析规则。

其中server的addSetNext规则说明了会调用栈顶对象的setServer方法,就是说调用Catalina类的setServer方法。【会将实例化的org.apache.catalina.core.StandardServer对象返到setServer方法】

Catalina.start() 方法分析

getServer().start();

对,核心代码,就这个一句话。

调用StandardServer.start();

关于这里的Server

这里所创建的server是org.apache.catalina.Server接口的一个实现类StandardServer。

public final class StandardServer extends LifecycleMBeanBase implements Server {}

这里涉及到了LifecycleMBeanBase,Tomcat的容器生命周期( Lifecycle j) (⊙_⊙)?

代码中最后的getServer().start()getServer().init()所指的就是Lifecycle接口的方法。

接下来要了解的就是这一个东东了。


参考

http://www.iocoder.cn/Tomcat/yuliu/Start-analysis-3-Digester/


小杭
邮箱:xiao_hang0_0@163.com


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小_杭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值