Tomcat 源码分析-启动分析(4)

38 篇文章 0 订阅
27 篇文章 0 订阅

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();
        }
    }

以上两个就可以看出,初始化的时候执行的流程,以下给出了一个调用的时序图,方便理解:

StandardServer LifecycleBase init() LifecycleBase 继承自Lifecycle接口 调用父类方法 init(){。。。。} ***发布状态BEFORE _INIT_EVENT*** 调用[abstract在St andardServer实现 ]initInternal() initInternal()实现方法 super.initInternal() 初始化旗下的子服务 ,这里就 for (int i = 0 , i < services.length , i++) { services[i].init(), } 本身,以及旗下服务初始化完成 ***发布状态AFTER_ INIT_EVENT*** 完成 StandardServer LifecycleBase StandardServer.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);
    }

至此,发布状态时间的前置工作已经完成了。

组件状态事件发布与事件被处理处理

在各个组件代码中(上面的初始化和启动源码中就有)会经常看到setStateInternalfireLifecycleEvent这两个方法的调用:像这样↓↓

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也是这个样子的。

StandardServer LifecycleSupport Listener 创建服务 实例化 1 : 1 绑定 实例化 Server 本身创建完成 创建监听器 实例化 xml解析回调 addLifecycl eListener() 实际调用 addLifecycl eListener() 添加到 内部侦听 对象数组 进行维护 监听器创建完成 发布事件状态 fireLifecycleEvent() 实际调用 fireLifecycleEvent() 遍历维护的监听数 遍历调用 lifecycleEvent() 具体处理事件。。 事件处理结束 StandardServer LifecycleSupport Listener 事件处理大概的时序图

Lifecycle 相关类 UML 关系图:

UML关系图

分析结束

到这里,整个的Tomcat的启动分析就结束了。【之后休息一段时间继续学习】

(从bat脚本文件开始,到java启动main方法,类加载器,xml解析并创建服务,最后以链式调用,事件通知的形式初始化并启动各个服务)

关于具体的各个server,listener等服务的具体内容,这里就不分析了,只做启动流程的分析。

具体的服务于监听,直接查看对应的实现类即可。


参考

http://www.iocoder.cn/Tomcat/yuliu/Start-analysis-5-Lifecycle/


小杭
邮箱:xiao_hang0_0@163.com


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小_杭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值