有时候面试时会被问tomcat启动时web.xml中节点(类似listener,filter等)被加载的顺序,死记硬背那多没品,正好手里有tomcat7的源码,找了点时间翻了翻。
让我们先来喵一眼tomcat的架构,大致了解下tomcat启动的顺序,那我们目前关心的仅仅是web.xml中的加载顺序,按照架构来讲肯定是在Context中,架构如下图:
TomcatArchitecture from
那我们就来到Context中寻找线索,按照tomcat架构设计Context的实现类是StandardContext,全称org.apache.catalina.core.StandardContext
看到其实现Lifecycle接口,我们在StandardContext中笑而不语的找到startInternal方法,看看我把暂时无语的代码去掉后的注释版
[java] view plaincopy在CODE上查看代码片派生到我的代码片 /**
- Start this component and implement the requirements
- of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
- @exception LifecycleException if this component detects a fatal error
- that prevents this component from being used */ @Override protectedsynchronized void startInternal() throwsLifecycleException { //设置webappLoader 代码省略
// Standard container startup 代码省略
try{
// Set up the context init params 初始化context-param节点数据
mergeParameters();// Configure and call application event listeners
//配置和调用listeners 也就是说开始监听 if(ok) { if(!listenerStart()) { log.error("Error listenerStart"); ok = false; } }// Configure and call application filters
//配置和调用filters filters开始起作用 if(ok) { if(!filterStart()) { log.error("Error filterStart"); ok = false; } }// Load and initialize all "load on startup" servlets
//加载和初始化配置在load on startup的servlets if(ok) { loadOnStartup(findChildren()); }// Start ContainerBackgroundProcessor thread
super.threadStart(); }finally{ // Unbinding thread unbindThread(oldCCL); }}
所以代码就是最好的文档就是这样,我们归纳一下代码1:首先是context-param节点
2:接着配置和调用listeners 并开始监听
3:然后配置和调用filters filters开始起作用
4:最后加载和初始化配置在load on startup的servlets
另外赠送一枚彩蛋,也就是load on startup中的启动顺序是按照配置参数从小到大加载实例化的(小于0的忽略),
源代码中是用一个TreeMap,其中键为Integer,那么就是按照配置参数默认从小到大排列启动。