启动过程
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);
}
-
- 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);
}
}
-
- 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;
}
}