Tomcat 源码分析-启动分析(4)
文章目录
Lifecycle 机制和实现原理
前面分析到
Catalina
的最后调用的是StandardServer的init()和start()
方法。这里就来看一下,这两个方法都发生了什么。
init()和 start()基础流程
首先分析一下,init()被调用的时候发生了什么操作:
先介绍一下
StandardServer
的基础接口为Lifecycle
接口 ,这个接口是各种组件都会以此作为父接口,其中定义了initInternal、startInternal
方法,所以通过这个就可以实现链式调用,完成所有服务的初始化和启动。然后开始看整个的流程:【其实就两个方法而已】
//类LifecycleBase的部分源码: public abstract class LifecycleBase implements Lifecycle { //。。。。。 @Override public final synchronized void init() throws LifecycleException { if (!state.equals(LifecycleState.NEW)) { invalidTransition(Lifecycle.BEFORE_INIT_EVENT); } try { //setStateInternal这个方法在后续有分析 setStateInternal(LifecycleState.INITIALIZING, null, false); initInternal(); //主要就是这个,实现了链式调用,以便初始化所有的服务 setStateInternal(LifecycleState.INITIALIZED, null, false); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); setStateInternal(LifecycleState.FAILED, null, false); throw new LifecycleException( sm.getString("lifecycleBase.initFail",toString()), t); } }
//类StandardServer的初始化代码 public final class StandardServer extends LifecycleMBeanBase implements Server { @Override protected void initInternal() throws LifecycleException { super.initInternal(); 。。。。。。。 // Initialize our defined Services for (int i = 0; i < services.length; i++) { services[i].init(); } }
以上两个就可以看出,初始化的时候执行的流程,以下给出了一个调用的时序图,方便理解:
然后是关于start()的方法,这个与init()方法类似了。
与上面的init调用类似,直接贴代码就可以咯:
public abstract class LifecycleBase implements Lifecycle { //... @Override public final synchronized void start() throws LifecycleException { //... if (state.equals(LifecycleState.NEW)) { init(); } else if (state.equals(LifecycleState.FAILED)) { stop(); } else if (!state.equals(LifecycleState.INITIALIZED) && !state.equals(LifecycleState.STOPPED)) { invalidTransition(Lifecycle.BEFORE_START_EVENT); } try { setStateInternal(LifecycleState.STARTING_PREP, null, false); startInternal(); //... setStateInternal(LifecycleState.STARTED, null, false); //... }
public final class StandardServer extends LifecycleMBeanBase implements Server { @Override protected void startInternal() throws LifecycleException { //发布状态 fireLifecycleEvent(CONFIGURE_START_EVENT, null); setState(LifecycleState.STARTING); globalNamingResources.start(); // Start our defined Services synchronized (servicesLock) { for (int i = 0; i < services.length; i++) { services[i].start(); } } }
到这里,tomcat算是已经启动起来了。
可以看到这里只是对初始化和启动进行,事件的发布,并没有涉及到具体的时间处理。
这是因为,这里是使用的是事件监听和事件通知的方式。具体针对该事件如何处理由监听器实现类自己决定。
下面,就来分析一下tomcat事件发布的相关分析,【而具体的事件处理,可以去看看对应的监听器的源码】
关于其中的事件发布监听等
这里从Server创建的时候说起,到监听器的注册关联,再到事件发布的执行。
初始创建Server的时候
在实例化Server接口实现类的时候,在其父类
LifecycleBase
中定义了
private LifecycleSupport lifecycle = new LifecycleSupport(this);
LifecycleSupport
类是作为生命周期监听器的管理类来统一发布事件。LifecycleSupport其部分核心如下:
public final class LifecycleSupport { public LifecycleSupport(Lifecycle lifecycle) { super(); this.lifecycle = lifecycle; } //类中存有监听器的素组 private LifecycleListener listeners[] = new LifecycleListener[0]; //。。。 //向该组件添加一个生命周期事件侦听器 public void addLifecycleListener(LifecycleListener listener) { synchronized (listenersLock) { LifecycleListener results[] = new LifecycleListener[listeners.length + 1]; for (int i = 0; i < listeners.length; i++) results[i] = listeners[i]; results[listeners.length] = listener; listeners = results; } } //... // 通知特定事件具有的所有生命周期事件侦听器 /* @param type Event type 事件类型 * @param data Event data 事件数据 */ public void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(lifecycle, type, data); LifecycleListener interested[] = listeners; for (int i = 0; i < interested.length; i++) interested[i].lifecycleEvent(event); } //...
LifecycleSupport核心的内容就是,提供了添加、维护侦听器列表【数组】,并提供发布事件,既通知所有侦听器事件。
PS:这里说明一下,作为各种事件处理的侦听器的接口:
public interface LifecycleListener { //确认指定事件的发生(事件的处理方法) public void lifecycleEvent(LifecycleEvent event); }
对,没有错,就只有一个方法,这个方法用作某个事件(
org.apache.catalina.LifecycleEvent
)产生时通知当前监听器的实现类,具体针对该事件如何处理由监听器实现类自己决定。
监听器的注册
Server下的监听器的定义是在server.xml配置文件里面定义的,在解析Server/Listener的时候,有这么个解析规则:
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"); //就是这个方法addLifecycleListener(在创建对象后会调用上层的此方法)
以StandardServer为例,旗下的服务和监听器会调用StandardServer.addLifecycleListener();
而且,此方法的实现在其父类LifecycleBase中:
public abstract class LifecycleBase implements Lifecycle { private LifecycleSupport lifecycle = new LifecycleSupport(this); //方法会调用到监听器管理类LifecycleSupport的addLifecycleListener进行维护。 //【上面已给出了LifecycleSupport源码】 public void addLifecycleListener(LifecycleListener listener) { lifecycle.addLifecycleListener(listener); }
至此,发布状态时间的前置工作已经完成了。
组件状态事件发布与事件被处理处理
在各个组件代码中(上面的初始化和启动源码中就有)会经常看到
setStateInternal
和fireLifecycleEvent
这两个方法的调用:像这样↓↓setStateInternal(LifecycleState.INITIALIZING, null, false); fireLifecycleEvent(CONFIGURE_START_EVENT, null);
- 首先先来看一下setStateInternal方法:(在父类LifecycleBase中定义)
private synchronized void setStateInternal(LifecycleState state, Object data, boolean check) throws LifecycleException { if (check) { //... if (!(state == LifecycleState.FAILED || (this.state == LifecycleState.STARTING_PREP && state == LifecycleState.STARTING) || (this.state == LifecycleState.STOPPING_PREP && state == LifecycleState.STOPPING) || (this.state == LifecycleState.FAILED && state == LifecycleState.STOPPING))) { // No other transition permitted 不予许其他情况通过 invalidTransition(state.name()); } } //核心代码为这里,把组件的新状态赋值到本身, //再调用fireLifecycleEvent方法发布组件状态(发布事件状态) this.state = state; String lifecycleEvent = state.getLifecycleEvent(); if (lifecycleEvent != null) { fireLifecycleEvent(lifecycleEvent, data); } } private void invalidTransition(String type) throws LifecycleException { String msg = sm.getString("lifecycleBase.invalidTransition", type, toString(), state); throw new LifecycleException(msg); }
这里设置完本身组件的状态,调用了发布事件的方法
fireLifecycleEvent()
;
- 发布事件的方法
fireLifecycleEvent();
:(在父类LifecycleBase中定义)public abstract class LifecycleBase implements Lifecycle { //... /* 这里时间发布调用了lifecycle对象的fireLifecycleEvent方法;*/ protected void fireLifecycleEvent(String type, Object data) { lifecycle.fireLifecycleEvent(type, data); } //... /*这里的lifecycle的定义如下,是LifecycleSupport类的,这个在上面的时候提到过的*/ private LifecycleSupport lifecycle = new LifecycleSupport(this);
这里调用了server绑定的LifecycleSupport监听时间管理类,而它的fireLifecycleEvent方法则是对所有管理的监听器遍历调用监听器接口定义的lifecycleEvent方法。
lifecycleEvent(),这个方法是监听器处理事件的方法。
这里随便找一个LifecycleListener接口的实现监听类来看看:
public class JasperListener implements LifecycleListener { //此侦听器用于在任何web应用程序初始化Jasper之前初始化Jasper @Override public void lifecycleEvent(LifecycleEvent event) { //看这个就开始处理对应事件类型的东东了 if (Lifecycle.BEFORE_INIT_EVENT.equals(event.getType())) { try { // Set JSP factory Class.forName("org.apache.jasper.compiler.JspRuntimeContext", true, this.getClass().getClassLoader()); } catch (Throwable t) { //...
整体的事件通知处理和Lifecycle 的关系分析
事件处理大概的时序图:
StandardServer类作为实例,所有server也是这个样子的。
Lifecycle 相关类 UML 关系图:
分析结束
到这里,整个的Tomcat的启动分析就结束了。【之后休息一段时间继续学习】
(从bat脚本文件开始,到java启动main方法,类加载器,xml解析并创建服务,最后以链式调用,事件通知的形式初始化并启动各个服务)
关于具体的各个server,listener等服务的具体内容,这里就不分析了,只做启动流程的分析。
具体的服务于监听,直接查看对应的实现类即可。
参考
http://www.iocoder.cn/Tomcat/yuliu/Start-analysis-5-Lifecycle/
小杭
邮箱:xiao_hang0_0@163.com