`

Tomcat7源码分析(二)组件生命周期详解

阅读更多
    在tomcat中起到生命周期的核心接口是Lifecycle看一下这个接口的方法签名:



    这个接口定义了所有组件可能处于的所有状态、增加获取删除监听器操作、组件初始化,开启,停止,注销操作和获取当前状态操作。

    在Lifecycle接口中所定义的状态还被封装到了一个枚举类中,可以看一下LifecycleState的源码:
public enum LifecycleState {
    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),
    MUST_STOP(true, null),
    MUST_DESTROY(false, null);

    private final boolean available;
    private final String lifecycleEvent;

    private LifecycleState(boolean available, String lifecycleEvent) {
        this.available = available;
        this.lifecycleEvent = lifecycleEvent;
    }
    public boolean isAvailable() {
        return available;
    }

    /**
     *
     */
    public String getLifecycleEvent() {
        return lifecycleEvent;
    }
}

    从以上源码可见LifecycleState枚举类就是对Lifecycle接口中的状态进行了封装。另外加了是否可用标志。
下面从我们所熟悉的StandardServer类入手开始讨论这些组件是怎么被初始化以及怎么被开启的。看一下StandardServer的继承图解:



    至此就引出了一个问题,LifecycleBase是个什么类。打开这个类的源码首先可以看到它实现了Lifecycle接口,即它是管理组件生命周期的最顶层的类。一般像这种高层次的类都是抽象的,这个类也不例外,它也是抽象的。
   
    下面开始讨论这个类的方法,首先继承LifecycleBase的底层组件类比如StandardServer它是不需要重写init,start,stop这三个方法的。因为这三个方法定义了组件状态转换的共性。比如init方法,所有组件在初始化时都要执行这个公共方法。先贴一下这个方法的源码:
 @Override
    public final synchronized void init() throws LifecycleException {
        if (!state.equals(LifecycleState.NEW)) {
            invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }
        setStateInternal(LifecycleState.INITIALIZING, null, false);

        try {
            initInternal();
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            setStateInternal(LifecycleState.FAILED, null, false);
            throw new LifecycleException(
                    sm.getString("lifecycleBase.initFail",toString()), t);
        }

        setStateInternal(LifecycleState.INITIALIZED, null, false);
    }

    其中有两点需要重点关注:
   
    1)setStateInternal:该方法的作用是重新设置该组件的状态。并且在状态改变时还伴随着事件监听器的执行。查看setStateInternal的代码不难发现它的核心代码如下:
 this.state = state;
        String lifecycleEvent = state.getLifecycleEvent();
        if (lifecycleEvent != null) {
            fireLifecycleEvent(lifecycleEvent, data);
        }

    先改变组件状态,然后查看该状态是否需要被监听器监听。如果被监听器监听就执行监听器。但是执行监听器说起来容易,它是怎么来的,它的监听机制又是什么?
现在追上这个方法看看它的实现过程:
 protected void fireLifecycleEvent(String type, Object data) {
        lifecycle.fireLifecycleEvent(type, data);
    }

这个lifecycle又是什么东西?它是LifecycleSupport类的一个实例。其实LifecycleBase是LifecycleSupport的一个代理类。所有监听器有关的方法LifecycleBase都是调用的LifecycleSupport中的方法。可以看一下LifecycleSupport的方法签名:



lifecycle是指该LifecycleSupport类是为哪个实现lifecycle接口的类服务的。listeners[]是监听器数组,addLifecycleListener是增加监听器,在tomcat容器启动时,使用Digester技术(没听过没关系,只要知道它是读取配置文件然后根据配置文件实例化对象就行)读取server.xml文件中的<Listener>标签,然后调用addLifecycleListener将配置的Listener添加到listeners[]中。removeLifecycleListener是移出监听器。fireLifecycleEvent是循环执行监听器数组中的每一个监听器。上面谈到的状态改变时就是执行的这个fireLifecycleEvent方法。

看到这里也许有的朋友已经忘了上文的init方法了,千万注意到此这只是谈到init方法中需要注意两点的第一点。那么现在开始第二点:

2)initInternal方法。它是个抽象方法也就是说该方法必须由子类重写。首先看它的直接子类LifecycleMBeanBase。看到这类的名字就能想到它可能与javabean管理有关。的确他复写了initInternal方法,其目的就是将该组件注册到JMX服务器中。对于具体注册过程先不做过多讨论,之后更新还会详细说明。StandardServer也重写了initInternal方法。并且第一行是:
 super.initInternal();

调用父类也就是LifecycleMBeanBase类中的initInternal方法,这时候这句话是万万不能省的,如果省了就不能向JMX服务器注册对象了。这一点要跟eclipse中自动生成构造方法第一行super.init();可写可不写区分开。在子类中重点代码如下:
 // Initialize our defined Services
        for (int i = 0; i < services.length; i++) {
            services[i].init();
        }

它执行了service的init方法。仔细回故上面的逻辑,整理一下思路,会发现tomcat的生命周期管理是何等的漂亮!

我将tomcat生命周期的实现过程从tomcat源码中抽离了出来,建立了一个小的Demo,有兴趣的朋友可以下载debug以此来整理思路,这样会更加直观。
地址:https://github.com/smallbug-vip/repo
  • 大小: 6.9 KB
  • 大小: 3.4 KB
  • 大小: 4.4 KB
0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics