在server.xml中的<Server>标签下看到了<Listener>子标签,这些Listener是用来干预Tomcat加载和启动的行为的,既然是能够配置的,那么Tomcat是否提供了这种方式供开发者能够开发自定义的逻辑来干预Tomcat喃,并且在其余<Service><Engine>等标签下面都可以生效喃。。。。我猜测是的,为何喃?由于Tomcat全部核心的组件都实现了Lifecyle接口,那么应该LifecycleListener也应该对全部接口都会有效,接下来就试着写一段实现类来证明一下,证明以后再从源码分析是如何让这些Listener生效的。java
自定义LifecycleListenerapache
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>标签下添加子标签ide
启动看效果源码分析
打印日志输出,说明添加的Listener生效了。。。那么添加到其余节点下是否是也会生效喃。。。答案是:<Server><Service><Engine><Connector><Context><Host>都是能够的,可是<Valve>不行,若是非要给Valve注入,只有经过父容器的Listener绕道达到效果了。spa
既然效果看到了,那就从源码侧面分析一下是如何实现的。3d
思考一下,首先是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的子类便可code
就能够。下面的列表也解释了为何Valve在server.xml中能够配置,且是Lifecycle接口的子类,就算配置了Listener也不生效的缘由(由于在解析的时候匹配不到规则,不会添加)server
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行为的目的。