Fork me on GitHub

Tomcat源码阅读之组件生命周期

start&stop

上篇说道Catalina中的load 和init 方法,提到了getServer().init(),和getServer().start(),这两个方法,本文主要通过这两个方法,进一步研究组件之间的关系和各种状态,希望先看一下server.xml配置文件中的组件关系图。

需要先了解一个知识点digester,讲xml文件转换成java对象,
常用的几个方法

  • digester.addObjectCreate(“Server”,”org.apache.catalina.core.StandardServer”,”className”);
  • digester.addSetProperties(“Server”);
  • digester.addSetNext(“Server”,”setServer”,”org.apache.catalina.Server”);

Catalina中的load方法

重点代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Digester digester = createStartDigester();
....
....
....
file = configFile();
inputStream = new FileInputStream(file);
inputSource = new InputSource(file.toURI().toURL().toString());
......
......
......
inputSource.setByteStream(inputStream);
digester.push(this);
digester.parse(inputSource);
....
....
....
getServer().setCatalina(this);
getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());
// Stream redirection
initStreams();
// Start the new server
getServer().init();
···
···
···
log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");

createStartDigester()设置规则,找到xml节点执行对应的方法,configFile()这里就是读取具体的配置文件server.xml,protected String configFile = "conf/server.xml";然后就是digester把Catalina push进来,parse进行解析xml。这里说明的是中间有一段 digester.addSetNext(“Server”,”setServer”,”org.apache.catalina.Server”);,这句就是执行setServer方法,对应的参数是org.apache.catalina.Server这种类型,然后上面还有一句,addObjectCreate,org.apache.catalina.core.StandardServer这个就是实际创建的对象类,这样就可以通过Catalina把Server联系起来的,之后的init()等这种方法,就都是调用的getServer(),上面这个对象了。

Standard其他类中的方法Server Service Connector Engine等

StandardServer.addService() 方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public void addService(Service service) {

service.setServer(this);

synchronized (servicesLock) {
Service results[] = new Service[services.length + 1];
System.arraycopy(services, 0, results, 0, services.length);
results[services.length] = service;
services = results;

if (getState().isAvailable()) {
try {
service.start();
} catch (LifecycleException e) {
// Ignore
}
}

// Report this property change to interested listeners
support.firePropertyChange("service", null, service);
}

}

每一个Server可以包含多个Service,一样通过Catalina的digester来调用addService方法,这里维护了一个数组,这也是神奇的地方,一对多的关系是用数组来维护的,虽然说java中没有所谓的动态数组概念,但是,这里通过

1
2
3
4
Service results[] = new Service[services.length + 1];
System.arraycopy(services, 0, results, 0, services.length);
results[services.length] = service;
services = results;

这四句话,System.arraycopy是native的方法,比较奇特。另外这个synchronized 了一个空对象private final Object servicesLock = new Object();来保证对services的操作是线程安全。其他的findService,findServices,removeService等都是如此操作,remove用的是for循环。

其他容器的关系调用方法

  • StandardService 中的 setContainer(是一个Engine,在EngineRuleSet中) addConnector addExecutor digester规则在Catalina里面对应 还有一个await方法没有讲☆
  • Connector 中的 addSslHostConfig
  • StandardEngine 中的 addChild(HostRuleSet)只添加Host、setCluster、addValve digester规则在EngineRuleSet里面对应
  • StandardHost 中的 addChild只添加Host,setCluster、addValve digester规则在HostRuleSet里面对应
    等等之类的调用关系,都在digester中

Lifecycle类

通过上面的init(),找到StandredServer,可发现这没有init方法,继续public final class StandardServer extends LifecycleMBeanBase implements Serverpublic abstract class LifecycleMBeanBase extends LifecycleBase implements JmxEnabled,public abstract class LifecycleBase implements Lifecycle,最终我们在这个抽象类LifecycleBase中发现了这个方法.然后就发现,这个init里面中会调用一个initInternal方法,这个在LifecycleBase中是一个抽象方法,这些集成了它的类都重写了,因此我们在getServer.init(),实际上就相当于调用initInternal。

模板方法

org.apache.catalina.LifecycleState 和 org.apache.catalina.Lifecycle 看最上面的图(此图也是在Lifecycle内):

1
2
3
4
5
6
7
8
9
10
11
12
NEW(false, null),
INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),
INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),
STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),
STARTING(true, Lifecycle.START_EVENT),
STARTED(true, Lifecycle.AFTER_START_EVENT),
STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),
STOPPING(false, Lifecycle.STOP_EVENT),
STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
FAILED(false, null);

12种状态: new(1) init(2) start(3) stop(3) destroy(2) failed(1)
Lifecycle有四个基本的方法,init start stop destroy 外加一个addLifecycleListener()事件监听
public abstract class LifecycleBase implements Lifecycle 这个org.apache.catalina.util.LifecycleBean中重写了上面四个方法(synchronized),然后这里又
在内部加一个initInternal方法调用,这里就用到了模板方法,在调用init的时候,前后做一些操作,判断当前状态啊,日志啊,等等。
另外这里又有一个方法fireLifecycleEvent,触发生命周期事件。

start&stop

一般所有的组件是实现的org.apache.catalina.util.LifecycleMBeanBase这个BaseBean的生命周期,重写了initInternal,然后在使用组件的时候对生命周期做得操作,init等就直接调用LifecycleMBeanBase,又调用本组件的initInternal.

见图StandardService中的initInternal方法:
start&stop

系列文章

参看文献:

文章目录
  1. 1. Catalina中的load方法
  2. 2. Standard其他类中的方法Server Service Connector Engine等
    1. 2.0.1. 其他容器的关系调用方法
  • 3. Lifecycle类
    1. 3.1. 模板方法
  • ,