深度解析Tomcat中StandardContext绑定ContextConfig监听器的过程

在上一篇分析Tomcat是如何初始化servlet文章中有谈到Lifecycle的观察者模式,但没有深入解释。其实在StandardContext的fireLifecleEvent方法中就是一个将事件向监听器传递的动作:

如下图所示: 

  protected void fireLifecycleEvent(String type, Object data) {
        // 构造一个事件:事件源=》Lifecycle组件,事件类型/数据由传入参数决定
        LifecycleEvent event = new LifecycleEvent(this, type, data);
        for (LifecycleListener listener : lifecycleListeners) {
            // 通过for循环将该事件通知给该lifecycle组件所持有的全部监听者
            listener.lifecycleEvent(event);
        }
    }

在这里我们预先给出一个结论:StandardContext的监听器Listener是ContextConfig

这里先不做解释,暂时记住这个结论就可以。

然后给出预备知识:什么叫观察者模式的事件监听机制?

一般来讲:

事件监听机制如下:

  • 事件源:事件发生的地方
  • 事件:在事件源发生的事件,比如:初始化上下文
  • 监听器:监听事件源的一个对象,拥有接收到事件时需要执行的逻辑
  • 注册监听:将事件、事件源、监听器绑定在一起。当事件源发生某个事件后,将事件传递给监听器,监听器执行相应代码逻辑 

在tomcat中所有继承LifecycleBase的组件都是事件源

下面我们来分析ContextConfig监听器是如何创建的,然后怎样绑定到StandardContext的

然后重新回到tomcat源码:

先定位到org.apache.catalina.startup.Catalina中load方法内的createStartDigester方法:

然后进入createStartDigester方法并定位到addRuleSet入参是new ContextRuleSet的部分:

接着进入Digester类的addRuleSet方法中的ruleSet.addRuleInstances(this)部分:

 

 这里说一下: digester是一个独立的开源项目,最初是给struct解析xml文件,后来引入到tomcat解析server.xml文件,当然实际上digester能做的远不止这些,下面继续进入addRuleInstances方法:

 可以看到RuleSet实际是一个接口,下面有很多实现类,但是参考之前的代码:前面addRuleSet入参是new ContextRuleSet,所以这里的实现类应该选择ContextRuleSet

进入到ContextRuleSet类后定位到addRuleInstances方法中digester.addRule方法中跟ContextConfig相关的代码: 

从这里我们大致已经可以推断:StandardContext已经跟ContextConfig监听器绑定了。

为什么这么说呢:

      1. 这里的LifecycleListenerRule的字眼已经很明显了:监听器规则嘛

      2.  prefix是ContextRuleSet类的属性,实际由构造器参数传入,回顾到catalina代码中的createStartDigester方法的addRuleSet代码段

 digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));

我们可以很容易推断:这里的prefix就是"Server/Service/Engine/Host/"

然后prefix + "Context"一拼接就成了"Server/Service/Engine/Host/Context"

这不就是StandardContext吗。 因为StandardContext是Context容器的具体实现类。

其实分析到了这一步就差不多了。

但是为了进一步充分证明这个推断,我们继续往下走,定位到digester.addRule方法:

 rule其实就是上面的ContextConfig监听器Listener。

备注:

继承关系:   LifecycleListenerRule => org.apache.tomcat.util.digester.Rule

继承关系:ContextRuleSet=》RuleSetBase =》RuleSet

rule.setDigester就是一个set方法,把入参pattern赋值给rule的digester属性,这里就不多说了:

 然后回到digester的addRule方法,而getRules返回的Rules,这里需要重点看一下Rules的add方法:

 可以看到add方法是一个接口,然后接着看它的实现类:

到这里就基本看的很清楚了: add方法的实现类是RulesBase,它的add方法有两个入参:

一个是pattern:其实就是被监听的组件,具体在这里就是StandardContext,

一个是Rule: 就是组件的监听器,具体在这里就是ContextConfig

因为一个组件的监听器可能不止一个,所以这里的监听器实际是一个List集合

然后查询监听器采用的是缓存机制:缓存实际是一个HashMap: key是组件名,value是组件的监听器集合List, 首先从缓存中查找,找不到就存到缓存中,同时更新缓存

 至此: StandardContext的监听器ContextConfig的绑定过程已经全部分析完毕

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值