赞
踩
承接上文,Catalina类通过load方法创建digester对象解析server.xml文件以获取Server对象.接下来就是Server启动流程的分析.
查看org.apache.catalina.Server接口的定义,可以看出start()方法是继承自org.apache.catalina.Lifecycle接口.Tomcat通过Lifecycle接口提供统一的组件生命周期管理.Lifecycle的接口注释很有趣,通过它可以很直观的了解组件生命周期管理流程,所以我把它贴进来.
/* * start() * ----------------------------- * | | * | init() | * NEW -»-- INITIALIZING | * | | | | ------------------«----------------------- * | | |auto | | | * | | \|/ start() \|/ \|/ auto auto stop() | * | | INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»--- | * | | | | | * | |destroy()| | | * | --»-----«-- ------------------------«-------------------------------- ^ * | | | | * | | \|/ auto auto start() | * | | STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»----- * | \|/ ^ | ^ * | | stop() | | | * | | -------------------------- | | * | | | | | * | | | destroy() destroy() | | * | | FAILED ----»------ DESTROYING ---«----------------- | * | | ^ | | * | | destroy() | |auto | * | --------»----------------- \|/ | * | DESTROYED | * | | * | stop() | * ----»-----------------------------»------------------------------ */
讲到接口不能只看方法签名呀,我们得找出接口的实现.还记得上文讨论Catalina类的load方法获取一个Server实例吗?这个Server接口的实例就来自于load中调用的createStartDigester方法.当时贴了一大段代码,可能你没注意到Server接口的实例,就在此时映射上去的:
// Configure the actions we will be using
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");
digester.addSetProperties("Server");
digester.addSetNext("Server",
"setServer",
"org.apache.catalina.Server");
看到这里我们就知道,Tomcat为每个组件接口提供了标准的实现类,Server接口对应的就是StandardServer.
StandardServer 类体里面没有实现start方法,而是通过继承生命周期管理基类LifecycleMBeanBase实现这一特性.而LifecycleMBeanBase继承了LifecycleBase.最后是LifecycleBase实现了Lifecycle接口.
这样做有啥好处呢?还是那句话组件之间生命周期的统一管理,把生命周期管理可重用部分的部分抽象出来,把需要组件定制的流程通过抽象方法延迟到子类中实现.
通过阅读LifecycleBase代码实现,我们可以看到init\start\stop\destroy中都有一些流程通过抽象方法延迟到StandardServer子类中实现.
/** * {@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); } try { setStateInternal(LifecycleState.STARTING_PREP, null, false); 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 { 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()); } } /** * 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 Start error occurred */ protected abstract void startInternal() throws LifecycleException; /** * Sub-classes implement this method to perform any instance initialisation * required. * * @throws LifecycleException If the initialisation fails */ protected abstract void initInternal() throws LifecycleException; /** * 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 Stop error occurred */ protected abstract void stopInternal() throws LifecycleException; /** * Sub-classes implement this method to perform any instance destruction * required. * * @throws LifecycleException If the destruction fails */ protected abstract void destroyInternal() throws LifecycleException;
/** * Start nested components ({@link Service}s) and implement the requirements * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}. * * @exception LifecycleException if this component detects a fatal error * that prevents this component from being used */ @Override protected void startInternal() throws LifecycleException { fireLifecycleEvent(CONFIGURE_START_EVENT, null); setState(LifecycleState.STARTING); globalNamingResources.start(); // Start our defined Services synchronized (servicesLock) { for (int i = 0; i < services.length; i++) { services[i].start(); } } if (periodicEventDelay > 0) { monitorFuture = getUtilityExecutor().scheduleWithFixedDelay( new Runnable() { @Override public void run() { startPeriodicLifecycleEvent(); } }, 0, 60, TimeUnit.SECONDS); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。