Tomcat8源码分析扩展点LifecycleListener及实现原理

编程

在server.xml中的<Server>标签下看到了<Listener>子标签,这些Listener是用来干预Tomcat加载和启动的行为的,既然是可以配置的,那么Tomcat是否提供了这种方式供开发者可以开发自定义的逻辑来干预Tomcat喃,而且在其他<Service><Engine>等标签下面都能够生效喃。。。。我猜想是的,为什么喃?因为Tomcat所有核心的组件都实现了Lifecyle接口,那么应该LifecycleListener也应该对所有接口都会有效,接下来就试着写一段实现类来证实一下,证实之后再从源码分析是如何让这些Listener生效的。

自定义LifecycleListener

public class MyLifecycleListener implements LifecycleListener {

@Override

public void lifecycleEvent(LifecycleEvent event) {

if(event.getType().equals(Lifecycle.BEFORE_INIT_EVENT)){

System.out.println("####################MyLifecycleListener output:"+Lifecycle.BEFORE_INIT_EVENT);

}

}

}

在server.xml中<Server>标签下添加子标签

启动看效果

打印日志输出,说明添加的Listener生效了。。。那么添加到其他节点下是不是也会生效喃。。。答案是:<Server><Service><Engine><Connector><Context><Host>都是可以的,但是<Valve>不行,如果非要给Valve注入,只有通过父容器的Listener绕道达到效果了。

 

既然效果看到了,那就从源码侧面分析一下是如何实现的。

思考一下,首先是Tomcat为什么能识别这些Listener,而且是不同的标签;加载了这些Listener什么时候被调用。。。其实在前面的章节中已经提到了,Catalina.createStartDigester()里面会设置很多规则,用于去匹配server.xml中的设置,就Listener而言,比如:org.apache.catalina.startup.Catalina#createStartDigester中的部分代码

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

这段代码的意思就是:在解析的时候要在Server下面创建一个LifecycleListener对象,并调用addLifecycleListener方法,将对象添加到组件的lifecycleListeners集合当中。

除了Server有这个配置,像下面的都有设置对应的规则,所以在解析的时候,只要他们的标签下面子标签设置了<Listener>,且对应的实现类是org.apache.catalina.LifecycleListener的子类即可

就可以。下面的列表也解释了为什么Valve在server.xml中可以配置,且是Lifecycle接口的子类,就算配置了Listener也不生效的原因(因为在解析的时候匹配不到规则,不会添加)

Server/Service/Listener

Server/Service/Connector/Listener

Server/Service/Engine/Listener

Server/Service/Engine/Host/Listener

Server/Service/Engine/Host/Context/Listener

接下来通过DEBUG证实一下,添加的Listener是否在解析完server.xml就已经实例化完,并且添加到对应的LifecycleListeners集合当中

通过上面的三张图确实证明了之前的猜想。在解析过程中,到底如何匹配的我就不贴出来了,感觉意义不大。

 

然后就是来看看Listener是在什么时候被调用的,MyLifecycleListener里面的判断是事件类型为BEFORE_INIT_EVENT,说明应该是在Catalina.load-init的时候被触发,将断点设置在

启动-调试-看结果

 

到这里就彻底说明了自定义LifecycleListener是如何在代码中进行加载和被调用的。

 

总结:

1.Tomcat源码看到这里,扩展点远不及Spring那么丰富,不过它也确实不需要那么多扩展点,毕竟没什么事不会去修改Tomcat的行为或者自己再在Tomcat的基础上搞一个MyTomcat出来。

2.LifecycleListener和生命周期有关,感觉只要是实现了Lifecycle接口的组件或者容器都可以添加LifecycleListener,但事实并不是如此,比如Valve就不行。它是Tomcat提供的扩展点之一,通过此扩展点可以往上或者往下拿到你想要的容器或者组件(DEBUG的时候看看对象的层次结构便知),对它们的状态进行修改即可达到影响Tomcat行为的目的。

 

以上是 Tomcat8源码分析扩展点LifecycleListener及实现原理 的全部内容, 来源链接: utcz.com/z/511548.html

回到顶部