欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-24 11:30:42
...
    在tomcat中起到生命周期的核心接口是Lifecycle看一下这个接口的方法签名:

Tomcat7源码分析(二)组件生命周期详解
            
    
    博客分类: Tomcat tomcat 

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

    在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的继承图解:

Tomcat7源码分析(二)组件生命周期详解
            
    
    博客分类: Tomcat tomcat 

    至此就引出了一个问题,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的方法签名:

Tomcat7源码分析(二)组件生命周期详解
            
    
    博客分类: Tomcat tomcat 

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
  • Tomcat7源码分析(二)组件生命周期详解
            
    
    博客分类: Tomcat tomcat 
  • 大小: 6.9 KB
  • Tomcat7源码分析(二)组件生命周期详解
            
    
    博客分类: Tomcat tomcat 
  • 大小: 3.4 KB
  • Tomcat7源码分析(二)组件生命周期详解
            
    
    博客分类: Tomcat tomcat 
  • 大小: 4.4 KB
相关标签: tomcat