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,下面的文章我们通过分析两个类的源码来搞懂相关功能的原理实现。

posted @ 2016-08-28 23:54  coldridgeValley  阅读(1764)  评论(0编辑  收藏  举报