zoukankan      html  css  js  c++  java
  • Tomcat中组件的生命周期管理(一)

    本文主要的目的是介绍了Catalina中所有组件的生命周期的概念以及整个生命周期的架构图。

    在之前的文章中介绍了tomcat整体的启动关闭流程,从流程中可以看出tomcat在启动和关闭的过程中涉及的组件相当之多,也可以看出tomcat是一个高度模块化的web容器。那么tomcat在启动关闭的时候是如何统一的管理所有的组件呢,之前在分析的时候也有所涉及,但是没有专门的去讲解,今天我们专门来看看这方面的相关作用原理。

    Catalina中包含多个组件,在启动的时候会依次启动所有的组件,在关闭的时候会依次关闭所有的组件,从而做到管理生命周期目的。在Catalina中生命周期的概念被抽象为LifeCycle接口,所有的需要Catalina管理的组件都必须实现LifeCycle接口。当然并不是一个Lifecycle接口就可以实现组件生命周期的目的,在Catalina中使用了很多相关的类,抽象类,接口来完成这件事情,我们可以先看下相关的类图。

    Lifecycle

    生命周期的顶层接口,在接口中定义了一些最基本的生命周期事件以及一些基础的方法。

    /**
     * The LifecycleEvent type for the "component after init" event.
     */
    public static final String BEFORE_INIT_EVENT = "before_init";
    /**
     * The LifecycleEvent type for the "component after init" event.
     */
    public static final String AFTER_INIT_EVENT = "after_init";
    /**
     * The LifecycleEvent type for the "component start" event.
     */
    public static final String START_EVENT = "start";
    
    ......
    
    public void addLifecycleListener(LifecycleListener listener);
    
    public LifecycleListener[] findLifecycleListeners();
    
    public void removeLifecycleListener(LifecycleListener listener);
    
    public void init() throws LifecycleException;
    
    public void start() throws LifecycleException;
    
    public void stop() throws LifecycleException;
    
    public void destroy() throws LifecycleException;
    

    通过源码可以看到,生命周期大致分为init,start,stop,destroy四步,每一步对应的事件有可能有 before事件 ,也有可能有 after事件。除此以外lifecycle接口还定义了对 事件监听器 LifecycleListener 的一些基本操作,包含添加,查找 ,删除。

    LifecycleEvent

    Catalina使用类LifecycleEvent来代表一个生命周期事件。

    /**
     * Construct a new LifecycleEvent with the specified parameters.
     *
     * @param lifecycle Component on which this event occurred
     * @param type Event type (required)
     * @param data Event data (if any)
     */
    public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
    
        super(lifecycle);
        this.type = type;
        this.data = data;
    }
    

    LifecycleEvent的构造函数需要传递一个Lifecycle实例,参数type所有的类型都在Lifecycle接口中定义的String类型的常量,参数data则是携带的一些参数。

    LifecycleListener

    生命周期的监听器,主要监听的是某个组件是否触发了哪个对应的生命周期事件。Lifecycle接口定义了对LifecycleListener的最基本的几个操作。LifecycleListener一般是在组件初始化的时候添加到组件的内部,在内部只定义了一个lifecycleEvent表示触发指定事件,如果需要对指定组件在指定生命周期事件的时候做一些事情,需要实现LifecycleListener接口,并且复写lifecycleEvent方法。

    public interface LifecycleListener {
    
    
    /**
     * Acknowledge the occurrence of the specified event.
     *
     * @param event LifecycleEvent that has occurred
     */
    public void lifecycleEvent(LifecycleEvent event);
    
    
    }
    

    LifecycleState

    lifecycleState是一个枚举,用来表示Catalina中组件当前的生命周期状态,查看源码可以知道组件总共具有12种(有两种会在tomcat9.x废弃,当前版本为tomcat7.x)生命周期状态,如下:

    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),
    /**
     * @deprecated Unused. Will be removed in Tomcat 9.0.x. The state transition
     *             checking in {@link org.apache.catalina.util.LifecycleBase}
     *             makes it impossible to use this state. The intended behaviour
     *             can be obtained by setting the state to
     *             {@link LifecycleState#FAILED} in
     *             <code>LifecycleBase.startInternal()</code>
     */
    @Deprecated
    MUST_STOP(true, null),
    /**
     * @deprecated Unused. Will be removed in Tomcat 9.0.x. The state transition
     *             checking in {@link org.apache.catalina.util.LifecycleBase}
     *             makes it impossible to use this state. The intended behaviour
     *             can be obtained by implementing {@link Lifecycle.SingleUse}.
     */
    @Deprecated
    MUST_DESTROY(false, null);
    

    可以看出生命周期状态和Lifecycle接口中定义的事件类息息相关。

    LifecycleSupport

    可以把这个类想想成一个工具类,这个类是实现组件触发生命周期监听器(LifecycleListener)的关键类,Catalina使用这个类完成了所有组件的关于LifecycleListener的添加,查找,删除,触发。后面我们会重点分析其源码,可以先大致浏览下。

    public final class LifecycleSupport {
     /**
     * Construct a new LifecycleSupport object associated with the specified
     * Lifecycle component.
     *
     * @param lifecycle The Lifecycle component that will be the source
     *  of events that we fire
    
    	构造器需要传入一个lifecycle实例
     */
    public LifecycleSupport(Lifecycle lifecycle) {
    
        super();
        this.lifecycle = lifecycle;
    
    }
    
    // ------------------------------成员变量
     /**
     * The source component for lifecycle events that we will fire.
     */
    private Lifecycle lifecycle = null;
    
    
    /**
     * The set of registered LifecycleListeners for event notifications.
        监听器 数组
     */
    private LifecycleListener listeners[] = new LifecycleListener[0];
    //用来同步的锁
    private final Object listenersLock = new Object(); // Lock object for changes to listeners
    
    
       /**
     * Add a lifecycle event listener to this component.
     *
     * @param listener The listener to add
     */
    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;
      }
    
    }
    
    
    /**
     * Get the lifecycle listeners associated with this lifecycle. If this 
     * Lifecycle has no listeners registered, a zero-length array is returned.
     */
    public LifecycleListener[] findLifecycleListeners() {
    
        return listeners;
    
    }
    
    
    /**
     * Notify all lifecycle event listeners that a particular event has
     * occurred for this Container.  The default implementation performs
     * this notification synchronously using the calling thread.
     *
     * @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);
    
    }
    
    
    /**
     * Remove a lifecycle event listener from this component.
     *
     * @param listener The listener to remove
     */
    public void removeLifecycleListener(LifecycleListener listener) {
    
        synchronized (listenersLock) {
            int n = -1;
            for (int i = 0; i < listeners.length; i++) {
                if (listeners[i] == listener) {
                    n = i;
                    break;
                }
            }
            if (n < 0)
                return;
            LifecycleListener results[] =
              new LifecycleListener[listeners.length - 1];
            int j = 0;
            for (int i = 0; i < listeners.length; i++) {
                if (i != n)
                    results[j++] = listeners[i];
            }
            listeners = results;
        }
    	
    }
    
    }
    

    从源码中我们可以看到该类构造器需要传递一个Lifecycle实例,内部成员变量包含一个LifecycleListener数组,以及实现了Lifecycle对应的添加,删除,查找方法,同时还有一个LifecycleListener的触发方法,具体的源码我们稍后进行分析。

    LifecycleBase

    Catalina使用LifecycleBase这个类来实现了所有关于生命周期的功能,包括了LifecycleListener的相关功能,我们先来查看下源码

    public abstract class LifecycleBase implements Lifecycle {
    
    private static Log log = LogFactory.getLog(LifecycleBase.class);
    
    private static StringManager sm =
        StringManager.getManager("org.apache.catalina.util");
    
    
    /**
     * Used to handle firing lifecycle events.
     * TODO: Consider merging LifecycleSupport into this class.
     */
    private LifecycleSupport lifecycle = new LifecycleSupport(this);
    
    
    /**
     * The current state of the source component.
     */
    private volatile LifecycleState state = LifecycleState.NEW;
    
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void addLifecycleListener(LifecycleListener listener) {
        lifecycle.addLifecycleListener(listener);
    }
    
    
    /**
     * {@inheritDoc}
     */
    @Override
    public LifecycleListener[] findLifecycleListeners() {
        return lifecycle.findLifecycleListeners();
    }
    
    
    /**
     * {@inheritDoc}
     */
    @Override
    public void removeLifecycleListener(LifecycleListener listener) {
        lifecycle.removeLifecycleListener(listener);
    }
    
    
    /**
     * Allow sub classes to fire {@link Lifecycle} events.
     * 
     * @param type  Event type
     * @param data  Data associated with event.
     */
    protected void fireLifecycleEvent(String type, Object data) {
        lifecycle.fireLifecycleEvent(type, data);
    }
    
    
    @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);
    }
    
    
    protected abstract void initInternal() throws LifecycleException;
    
    /**
     * {@inheritDoc}
     */
    @Override
    public final synchronized void start() throws LifecycleException {
        
        if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
                LifecycleState.STARTED.equals(state)) {
            
            if (log.isDebugEnabled()) {
                Exception e = new LifecycleException();
                log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
            } else if (log.isInfoEnabled()) {
                log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
            }
            
            return;
        }
        
        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);
        }
    
        setStateInternal(LifecycleState.STARTING_PREP, null, false);
    
        try {
            startInternal();
        } catch (Throwable t) {
            // This is an 'uncontrolled' failure so put the component into the
            // FAILED state and throw an exception.
            ExceptionUtils.handleThrowable(t);
            setStateInternal(LifecycleState.FAILED, null, false);
            throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t);
        }
    
        if (state.equals(LifecycleState.FAILED)) {
            // This is a 'controlled' failure. The component put itself into the
            // FAILED state so call stop() to complete the clean-up.
            stop();
        } else if (!state.equals(LifecycleState.STARTING)) {
            // Shouldn't be necessary but acts as a check that sub-classes are
            // doing what they are supposed to.
            invalidTransition(Lifecycle.AFTER_START_EVENT);
        } else {
            setStateInternal(LifecycleState.STARTED, null, false);
        }
    }
    
    
    /**
     * Sub-classes must ensure that the state is changed to
     * {@link LifecycleState#STARTING} during the execution of this method.
     * Changing state will trigger the {@link Lifecycle#START_EVENT} event.
     * 
     * If a component fails to start it may either throw a
     * {@link LifecycleException} which will cause it's parent to fail to start
     * or it can place itself in the error state in which case {@link #stop()}
     * will be called on the failed component but the parent component will
     * continue to start normally.
     * 
     * @throws LifecycleException
     */
    protected abstract void startInternal() throws LifecycleException;
    
    
    /**
     * {@inheritDoc}
     */
    @Override
    public final synchronized void stop() throws LifecycleException {
    
        if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) ||
                LifecycleState.STOPPED.equals(state)) {
    
            if (log.isDebugEnabled()) {
                Exception e = new LifecycleException();
                log.debug(sm.getString("lifecycleBase.alreadyStopped", toString()), e);
            } else if (log.isInfoEnabled()) {
                log.info(sm.getString("lifecycleBase.alreadyStopped", toString()));
            }
            
            return;
        }
        
        if (state.equals(LifecycleState.NEW)) {
            state = LifecycleState.STOPPED;
            return;
        }
    
        if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) {
            invalidTransition(Lifecycle.BEFORE_STOP_EVENT);
        }
        
        if (state.equals(LifecycleState.FAILED)) {
            // Don't transition to STOPPING_PREP as that would briefly mark the
            // component as available but do ensure the BEFORE_STOP_EVENT is
            // fired
            fireLifecycleEvent(BEFORE_STOP_EVENT, null);
        } else {
            setStateInternal(LifecycleState.STOPPING_PREP, null, false);
        }
    
        try {
            stopInternal();
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            setStateInternal(LifecycleState.FAILED, null, false);
            throw new LifecycleException(sm.getString("lifecycleBase.stopFail",toString()), t);
        } finally {
            if (this instanceof Lifecycle.SingleUse) {
                // Complete stop process first
                setStateInternal(LifecycleState.STOPPED, null, false);
                destroy();
                return;
            }
        }
    
        // Shouldn't be necessary but acts as a check that sub-classes are
        // doing what they are supposed to.
        if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) {
            invalidTransition(Lifecycle.AFTER_STOP_EVENT);
        }
    
        setStateInternal(LifecycleState.STOPPED, null, false);
    }
    
    
    /**
     * Sub-classes must ensure that the state is changed to
     * {@link LifecycleState#STOPPING} during the execution of this method.
     * Changing state will trigger the {@link Lifecycle#STOP_EVENT} event.
     * 
     * @throws LifecycleException
     */
    protected abstract void stopInternal() throws LifecycleException;
    
    
    @Override
    public final synchronized void destroy() throws LifecycleException {
        if (LifecycleState.FAILED.equals(state)) {
            try {
                // Triggers clean-up
                stop();
            } catch (LifecycleException e) {
                // Just log. Still want to destroy.
                log.warn(sm.getString(
                        "lifecycleBase.destroyStopFail", toString()), e);
            }
        }
    
        if (LifecycleState.DESTROYING.equals(state) ||
                LifecycleState.DESTROYED.equals(state)) {
    
            if (log.isDebugEnabled()) {
                Exception e = new LifecycleException();
                log.debug(sm.getString("lifecycleBase.alreadyDestroyed", toString()), e);
            } else if (log.isInfoEnabled() && !(this instanceof Lifecycle.SingleUse)) {
                // Rather than have every component that might need to call
                // destroy() check for SingleUse, don't log an info message if
                // multiple calls are made to destroy()
                log.info(sm.getString("lifecycleBase.alreadyDestroyed", toString()));
            }
            
            return;
        }
        
        if (!state.equals(LifecycleState.STOPPED) &&
                !state.equals(LifecycleState.FAILED) &&
                !state.equals(LifecycleState.NEW) &&
                !state.equals(LifecycleState.INITIALIZED)) {
            invalidTransition(Lifecycle.BEFORE_DESTROY_EVENT);
        }
    
        setStateInternal(LifecycleState.DESTROYING, null, false);
        
        try {
            destroyInternal();
        } catch (Throwable t) {
            ExceptionUtils.handleThrowable(t);
            setStateInternal(LifecycleState.FAILED, null, false);
            throw new LifecycleException(
                    sm.getString("lifecycleBase.destroyFail",toString()), t);
        }
        
        setStateInternal(LifecycleState.DESTROYED, null, false);
    }
    
    
    protected abstract void destroyInternal() throws LifecycleException;
    
    /**
     * {@inheritDoc}
     */
    @Override
    public LifecycleState getState() {
        return state;
    }
    
    
    /**
     * {@inheritDoc}
     */
    @Override
    public String getStateName() {
        return getState().toString();
    }
    
    
    /**
     * Provides a mechanism for sub-classes to update the component state.
     * Calling this method will automatically fire any associated
     * {@link Lifecycle} event. It will also check that any attempted state
     * transition is valid for a sub-class.
     * 
     * @param state The new state for this component
     */
    protected synchronized void setState(LifecycleState state)
            throws LifecycleException {
        setStateInternal(state, null, true);
    }
    
    
    /**
     * Provides a mechanism for sub-classes to update the component state.
     * Calling this method will automatically fire any associated
     * {@link Lifecycle} event. It will also check that any attempted state
     * transition is valid for a sub-class.
     * 
     * @param state The new state for this component
     * @param data  The data to pass to the associated {@link Lifecycle} event
     */
    protected synchronized void setState(LifecycleState state, Object data)
            throws LifecycleException {
        setStateInternal(state, data, true);
    }
    
    private synchronized void setStateInternal(LifecycleState state,
            Object data, boolean check) throws LifecycleException {
        
        if (log.isDebugEnabled()) {
            log.debug(sm.getString("lifecycleBase.setState", this, state));
        }
        
        if (check) {
            // Must have been triggered by one of the abstract methods (assume
            // code in this class is correct)
            // null is never a valid state
            if (state == null) {
                invalidTransition("null");
                // Unreachable code - here to stop eclipse complaining about
                // a possible NPE further down the method
                return;
            }
            
            // Any method can transition to failed
            // startInternal() permits STARTING_PREP to STARTING
            // stopInternal() permits STOPPING_PREP to STOPPING and FAILED to
            // STOPPING
            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());
            }
        }
        
        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);
    }
    }
    

    从源码上我们可以把LifecycleBase类的功能分为两个部分。第一部分是是关于LifecycleListener的相关功能,例如添加,删除,查找,触发相关事件,这部分功能都由LifecycleBase内部的成员变量LifecycleSupport完成。第二部分是关于接口Lifecycle相关方法的实现。简单总结就是LifecycleBase这个类用来实现关于生命周期的所有功能,其中分两部分,跟监听器有关系的功能由内部成员变量LifecycleBase实例实现,另外一部分就是实现了Lifecycle接口内部定义的所有方法。

    通过上面的介绍我们大致了解了关于生命周期所有类的功能作用,可以发现最重要的两个类就是LifecycleSupportLifecycleBase,下面的文章我们通过分析两个类的源码来搞懂相关功能的原理实现。

  • 相关阅读:
    ReSharper Tips—GotoImplementation
    Possible multiple enumeration of IEnumerable
    Hello, Razor!
    自话自说——POI使用需要注意一个地方
    css中怎么设置透明度的问题
    记录排查国标直播流播放卡顿的问题
    互联网上做广告的优点
    C#、.Net经典面试题集锦(一)
    什么是MFC
    C/S与B/S 的区别
  • 原文地址:https://www.cnblogs.com/coldridgeValley/p/5816406.html
Copyright © 2011-2022 走看看