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/ListenerServer/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