Tomcat-Lifecycle接口

启动过程

Tomcat 的/bin目录下的脚本startup.sh来启动Tomcat

在这里插入图片描述

Lifecycle -生命周期接口

Lifecycle接口是一个公用的接口,定义了组件生命周期的一些方法,用于启动、停止Catalina组件。它是一个非常重要的接口,组件的生命周期包括:init、start、stop、destory,以及各种事件的常量、,典型的观察者模式

在这里插入图片描述

public interface Lifecycle {
//初始化之前的事件
    String BEFORE_INIT_EVENT = "before_init";
    //初始化完成事件
    String AFTER_INIT_EVENT = "after_init";
    //启动事件
    String START_EVENT = "start";
    //启动前事件
    String BEFORE_START_EVENT = "before_start";
    //启动之后
    String AFTER_START_EVENT = "after_start";
    //停止事件
    String STOP_EVENT = "stop";
    //停止之前
    String BEFORE_STOP_EVENT = "before_stop";
    //停止之后
    String AFTER_STOP_EVENT = "after_stop";
    //销毁之后事件
    String AFTER_DESTROY_EVENT = "after_destroy";
    //销毁之前
    String BEFORE_DESTROY_EVENT = "before_destroy";
    //周期事件
    String PERIODIC_EVENT = "periodic";
    //配置启动
    String CONFIGURE_START_EVENT = "configure_start";
    //配置停止
    String CONFIGURE_STOP_EVENT = "configure_stop";
    //添加生命周期监听器
    void addLifecycleListener(LifecycleListener var1);
	//查找所有生命周期监听器
    LifecycleListener[] findLifecycleListeners();
	//移除监听器
    void removeLifecycleListener(LifecycleListener var1);
   //生命周期-初始化
    void init() throws LifecycleException;
	//生命周期-启动
    void start() throws LifecycleException;
	//生命周期-停止
    void stop() throws LifecycleException;
//生命周期-销毁
    void destroy() throws LifecycleException;
//生命周期-获取状态
    LifecycleState getState();
//生命周期-获取状态名称
    String getStateName();

    public interface SingleUse {
    }
}

在这里插入图片描述

LifecycleState-生命周期状态
public enum LifecycleState {
//new TomcatServer
    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);
    //是否活的 STARTING    STARTED   STOPPING_PREP为true,上面的枚举有具体的值
    private final boolean available;
    //事件
    private final String lifecycleEvent;

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

    /**
     * May the public methods other than property getters/setters and lifecycle
     * methods be called for a component in this state? It returns
     * <code>true</code> for any component in any of the following states:
     * <ul>
     * <li>{@link #STARTING}</li>
     * <li>{@link #STARTED}</li>
     * <li>{@link #STOPPING_PREP}</li>
     * </ul>
     *
     * @return <code>true</code> if the component is available for use,
     *         otherwise <code>false</code>
     */
    public boolean isAvailable() {
        return available;
    }

    public String getLifecycleEvent() {
        return lifecycleEvent;
    }
}
LifecycleBase 基础实现
public abstract class LifecycleBase implements Lifecycle {

在这里插入图片描述

LifecycleBase 实现了Lifecycle的所有方法

  • LifecycleBase:它实现了Lifecycle的init、start、stop等主要逻辑,向注册在LifecycleBase内部的LifecycleListener发出对应的事件,并且预留了initInternal、startInternal、stopInternal等模板方法,便于子类完成自己的逻辑

  • init方法

    @Override
    public final synchronized void init() throws LifecycleException {
    //不是new 状态
        if (!state.equals(LifecycleState.NEW)) {
        //抛出异常 1.
            invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
        }

        try {
        //2. 设置状态为初始化。。并发送事件
            setStateInternal(LifecycleState.INITIALIZING, null, false);
            //留给子类去实现3. 
            initInternal();
            //设置状态为初始化完成
            setStateInternal(LifecycleState.INITIALIZED, null, false);
        } catch (Throwable t) {
            handleSubClassException(t, "lifecycleBase.initFail", toString());
        }
    }


    /**
     * Sub-classes implement this method to perform any instance initialisation
     * required.
     *
     * @throws LifecycleException If the initialisation fails
     */
     //3 .具体的子类去实现
    protected abstract void initInternal() throws LifecycleException;
  private void invalidTransition(String type) throws LifecycleException {
        String msg = sm.getString("lifecycleBase.invalidTransition", type, toString(), state);
        throw new LifecycleException(msg);
    }
    1. setStateInternal
    //同步加锁的
   private synchronized void setStateInternal(LifecycleState state, Object data, boolean check)
            throws LifecycleException {

        if (log.isDebugEnabled()) {
            log.debug(sm.getString("lifecycleBase.setState", this, state));
        }
        //默认false
        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);
        }
    }
    1. fireLifecycleEvent

 protected void fireLifecycleEvent(String type, Object data) {
 //创建事件
        LifecycleEvent event = new LifecycleEvent(this, type, data);
        //发出事件通知,遍历内部所有的LifecycleListener,并调用其lifecycleEvent
        for (LifecycleListener listener : lifecycleListeners) {
   
            listener.lifecycleEvent(event);
        }
    }
LifecycleListener
public interface LifecycleListener {


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


}

Lifecycle组件的init、start、stop、destory的套路基本上一样,先由LifecycleBase完成前期的校验、事件通知动作,再调用子类的方法完成自己的逻辑

start过程会触发LifecycleState的STARTING_PREP、STARTED事件,如果出现启动失败还会触发FAILED事件,并且调用stop。因为会涉及多线程操作,因此对方法加了锁。如果start期间出现了异常,则会调用stop停止tomcat,或者state状态有误也会抛出异常

在这里插入图片描述

start 方法

    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;
        }
		
		 完成init初始化 判断如果是New就是调init方法
        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 {
         // 发出STARTING_PREP事件
            setStateInternal(LifecycleState.STARTING_PREP, null, false);
            //调用子类的startInternal方法
            startInternal();
            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 {
            //设置STARTED,并发送通知  成功完成start,发出STARTED事件
                setStateInternal(LifecycleState.STARTED, null, false);
            }
        } catch (Throwable t) {
            // This is an 'uncontrolled' failure so put the component into the
            // FAILED state and throw an exception.
            handleSubClassException(t, "lifecycleBase.startFail", toString());
        }
    }
LifecycleMBeanBase

LifecycleMBeanBase是LifecycleBase的直接子类,实现了JmxEnabled接口,很多组件都是直接继承它

public abstract class LifecycleMBeanBase extends LifecycleBase
        implements JmxEnabled {

在这里插入图片描述

LifecycleMBeanBase完成了jmx注册的主要逻辑,重写了LifecycleBase的initInternal、destroyInternal方法,用于完成jmx的注册、注销动作,这两个模板方法中特别说明:

  • 在initInternal阶段初始化MBeanServer实例,并且把当前实例注册到jmx中;
  • 而destroyInternal阶段则是根据ObjectName注销MBean

/**
     * Sub-classes wishing to perform additional initialization should override
     * this method, ensuring that super.initInternal() is the first call in the
     * overriding method.
     */
    @Override
    protected void initInternal() throws LifecycleException {
        // If oname is not null then registration has already happened via
        // preRegister().
        if (oname == null) {
            mserver = Registry.getRegistry(null, null).getMBeanServer();

            oname = register(this, getObjectNameKeyProperties());
        }
    }
  /**
     * Sub-classes wishing to perform additional clean-up should override this
     * method, ensuring that super.destroyInternal() is the last call in the
     * overriding method.
     */
    @Override
    protected void destroyInternal() throws LifecycleException {
        unregister(oname);
    }

为了保证jmx的正常注册和注销,要求子类在重写initInternal、destroyInternal方法时,必须先调用super.initInternal()。例如Connector:


public class Connector extends LifecycleMBeanBase  {
...
@Override
    protected void initInternal() throws LifecycleException {
      // 先行调用LifecycleMBeanBase的initInternal
        super.initInternal();
        ...
         //Initialize adapter
        }
    @Override
    protected void destroyInternal() throws LifecycleException {
    //先进行一些组件的销毁
        try {
            if (protocolHandler != null) {
                protocolHandler.destroy();
            }
        } catch (Exception e) {
            throw new LifecycleException(
                    sm.getString("coyoteConnector.protocolHandlerDestroyFailed"), e);
        }

        if (getService() != null) {
        //移除连接器
            getService().removeConnector(this);
        }
        //后调用父类的LifecycleMBeanBase的destroyInternal方法
        super.destroyInternal();
    }
}
LifecycleMBeanBase 类完成代码
public abstract class LifecycleMBeanBase extends LifecycleBase
        implements JmxEnabled {

    private static final Log log = LogFactory.getLog(LifecycleMBeanBase.class);
  //日志输出
    private static final StringManager sm =
        StringManager.getManager("org.apache.catalina.util");


    /* Cache components of the MBean registration. */
    //jmx的域,默认使用Service的name,即"Catalina"
    private String domain = null;
    // 用于标识一个MBean的对象名称,也可以根据这个name来查找MBean
    private ObjectName oname = null;
    //jmx的核心组件,提供代理端操作MBean的接口,提供了创建、注册、删除MBean的接口,它由MBeanServerFactory创建
    @Deprecated
    protected MBeanServer mserver = null;

    /**
     * Sub-classes wishing to perform additional initialization should override
     * this method, ensuring that super.initInternal() is the first call in the
     * overriding method.
     */
    @Override
    protected void initInternal() throws LifecycleException {
        // If oname is not null then registration has already happened via
        // preRegister().
        if (oname == null) {
            mserver = Registry.getRegistry(null, null).getMBeanServer();

            oname = register(this, getObjectNameKeyProperties());
        }
    }


    /**
     * Sub-classes wishing to perform additional clean-up should override this
     * method, ensuring that super.destroyInternal() is the last call in the
     * overriding method.
     */
    @Override
    protected void destroyInternal() throws LifecycleException {
        unregister(oname);
    }


    /**
     * Specify the domain under which this component should be registered. Used
     * with components that cannot (easily) navigate the component hierarchy to
     * determine the correct domain to use.
     */
    @Override
    public final void setDomain(String domain) {
        this.domain = domain;
    }


    /**
     * Obtain the domain under which this component will be / has been
     * registered.
     */
    @Override
    public final String getDomain() {
        if (domain == null) {
            domain = getDomainInternal();
        }

        if (domain == null) {
            domain = Globals.DEFAULT_MBEAN_DOMAIN;
        }

        return domain;
    }


    /**
     * Method implemented by sub-classes to identify the domain in which MBeans
     * should be registered.
     *
     * @return  The name of the domain to use to register MBeans.
     */
    protected abstract String getDomainInternal();


    /**
     * Obtain the name under which this component has been registered with JMX.
     */
    @Override
    public final ObjectName getObjectName() {
        return oname;
    }


    /**
     * Allow sub-classes to specify the key properties component of the
     * {@link ObjectName} that will be used to register this component.
     *
     * @return  The string representation of the key properties component of the
     *          desired {@link ObjectName}
     */
    protected abstract String getObjectNameKeyProperties();


    /**
     * Utility method to enable sub-classes to easily register additional
     * components that don't implement {@link JmxEnabled} with an MBean server.
     * <br>
     * Note: This method should only be used once {@link #initInternal()} has
     * been called and before {@link #destroyInternal()} has been called.
     *
     * @param obj                       The object the register
     * @param objectNameKeyProperties   The key properties component of the
     *                                  object name to use to register the
     *                                  object
     *
     * @return  The name used to register the object
     */
    protected final ObjectName register(Object obj,
            String objectNameKeyProperties) {

        // Construct an object name with the right domain
        StringBuilder name = new StringBuilder(getDomain());
        name.append(':');
        name.append(objectNameKeyProperties);

        ObjectName on = null;

        try {
            on = new ObjectName(name.toString());
            Registry.getRegistry(null, null).registerComponent(obj, on, null);
        } catch (MalformedObjectNameException e) {
            log.warn(sm.getString("lifecycleMBeanBase.registerFail", obj, name),
                    e);
        } catch (Exception e) {
            log.warn(sm.getString("lifecycleMBeanBase.registerFail", obj, name),
                    e);
        }

        return on;
    }


    /**
     * Utility method to enable sub-classes to easily unregister additional
     * components that don't implement {@link JmxEnabled} with an MBean server.
     * <br>
     * Note: This method should only be used once {@link #initInternal()} has
     * been called and before {@link #destroyInternal()} has been called.
     *
     * @param objectNameKeyProperties   The key properties component of the
     *                                  object name to use to unregister the
     *                                  object
     */
    protected final void unregister(String objectNameKeyProperties) {
        // Construct an object name with the right domain
        StringBuilder name = new StringBuilder(getDomain());
        name.append(':');
        name.append(objectNameKeyProperties);
        Registry.getRegistry(null, null).unregisterComponent(name.toString());
    }


    /**
     * Utility method to enable sub-classes to easily unregister additional
     * components that don't implement {@link JmxEnabled} with an MBean server.
     * <br>
     * Note: This method should only be used once {@link #initInternal()} has
     * been called and before {@link #destroyInternal()} has been called.
     *
     * @param on    The name of the component to unregister
     */
    protected final void unregister(ObjectName on) {
        Registry.getRegistry(null, null).unregisterComponent(on);
    }


    /**
     * Not used - NOOP.
     */
    @Override
    public final void postDeregister() {
        // NOOP
    }


    /**
     * Not used - NOOP.
     */
    @Override
    public final void postRegister(Boolean registrationDone) {
        // NOOP
    }


    /**
     * Not used - NOOP.
     */
    @Override
    public final void preDeregister() throws Exception {
        // NOOP
    }


    /**
     * Allows the object to be registered with an alternative
     * {@link MBeanServer} and/or {@link ObjectName}.
     */
    @Override
    public final ObjectName preRegister(MBeanServer server, ObjectName name)
            throws Exception {

        this.mserver = server;
        this.oname = name;
        this.domain = name.getDomain().intern();

        return oname;
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值