之前我拜读了《How Tomcat Works》这本书,对tomcat的架构与里面的实现有了一定的了解,现在借着tomcat的源码来深入了解这个精巧的艺术品。
首先从初始化开始,
getServer().init();
前面类加载的过程与digester读取xml文件的过程我先跳过,直接来看tomcat是怎么初始化的。
public final synchronized void init() throws LifecycleException {
// 1
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
// 2
setStateInternal(LifecycleState.INITIALIZING, null, false);
try {
// 模板方法
/**
* 采用模板方法模式来对所有支持生命周期管理的组件的生命周期各个阶段进行了总体管理,
* 每个需要生命周期管理的组件只需要继承这个基类,
* 然后覆盖对应的钩子方法即可完成相应的声明周期阶段的管理工作
*/
initInternal();
} catch (Throwable t) {
...
}
// 3
setStateInternal(LifecycleState.INITIALIZED, null, false);
}
3.这个init()方法,先将状态设置为正在初始化,然后调用initInternal()方法,这个方法很有意思,这是个抽象方法,然后因为standardServer这个子类实现了这个方法,并且之前是getServer.init(),根据java多态的原则,就会调用standardServer的initInternal()方法
protected void initInternal() throws LifecycleException {
super.initInternal();
// Register global String cache
// Note although the cache is global, if there are multiple Servers
// present in the JVM (may happen when embedding) then the same cache
// will be registered under multiple names
onameStringCache = register(new StringCache(), "type=StringCache");
// Register the MBeanFactory
MBeanFactory factory = new MBeanFactory();
factory.setContainer(this);
onameMBeanFactory = register(factory, "type=MBeanFactory");
// Register the naming resources
globalNamingResources.init();
// Populate the extension validator with JARs from common and shared
// class loaders
...
// Initialize our defined Services
for (int i = 0; i < services.length; i++) {
services[i].init();
}
}
4.这个方法的第一行 super.initInternal();调用了其父类的initInternal()方法,根据上面的继承关系图可以看出,这调用的是LifecycleMBeanBase的initInternal()方法
protected void initInternal() throws LifecycleException {
// If oname is not null then registration has already happened via
// preRegister().
if (oname == null) {
mserver = Registry.getRegistry(null, null).getMBeanServer();
oname = register(this, getObjectNameKeyProperties());
}
}
5.这个方法很简洁,作用就是将容器注册到MBeanServer里面,便于管理
6.然后回到standardServer的initInternal方法,接下来就是注册MBeanFactory,初始化NamingResources这一系列的动作
7.然后standardServer就会去初始化底下的service
for (int i = 0; i < services.length; i++) {
services[i].init();
}
8.然后又回到我们熟悉的节奏了,调用services的init()方法,这里自然地调到LifecycleBase的init()方法
9.LifecycleBase方法中的模板方法随后就调了standardService中的initInternal()方法:
protected void initInternal() throws LifecycleException {
super.initInternal();
if (container != null) {
container.init();
}
// Initialize any Executors
for (Executor executor : findExecutors()) {
if (executor instanceof LifecycleMBeanBase) {
((LifecycleMBeanBase) executor).setDomain(getDomain());
}
executor.init();
}
// Initialize our defined Connectors
synchronized (connectors) {
for (Connector connector : connectors) {
try {
connector.init();
} catch (Exception e) {
String message = sm.getString(
"standardService.connector.initFailed", connector);
log.error(message, e);
if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
throw new LifecycleException(message);
}
}
}
}
10.这里与standardServer很像,第一步都钓了父类也就是LifecycleMBeanBase的initInternal方法,将standardService注册到了MBeanServer中,接着,调用了container.init()
11.从继承关系图中可以看到containerBase是standardEngine、standardContext、standardHost、standardWrapper的父类是LifecycleMBeanBase的子类,这也就意味着,会先调用LifecycleBase的init()方法,然后就先后调用containerBase与standardEngine的initInternal方法,并且在途中都会将自己注册到MBeanServer中
12.初始化完容器,接下来初始化connector,在初始化connector途中会对mapperListener进行初始化