请结合Servlet工作原理阅读
在这之前,我简单的讲述一下观察者模式:
观察者模式又叫做发布-订阅(Publish/Subscribe)模式、源-监听(Source/Listener)模式。它定义了一种一对多的依赖关系,一个主题,多个观察者,当主题发生变化的时候,会主动的通知观察者,这样观察者便能针对主题发生的变化,执行某些对应的动作。观察者模式的应用非常广泛,如Java AWT事件模型,Servlet的监听器,Spring事件处理机制以及本文所讲述的Tomcat生命周期管理机制等等。
-
观察者模式
图片.png
实现该模式,通常需要两个过程:
-
订阅者订阅
图片.png -
发布者发布
图片.png
下面我给出一个具体示例:
抽象主题
-
package com.liyaocai;
/**
* 抽象主题 .
*
* @author liyaocai
* @version V1.0
* @date 2018/8/17 15:31
* @since 1.8
*/
public interface Observable {
/**
* 添加观察者
* @author liyaocai
* @param observer
* @return
* @throws
*/
void addObsrver(Observer observer);
/**
* 删除观察者
* @author liyaocai
* @param observer
* @return
* @throws
*/
void deletebserver(Observer observer);
/**
* 事件发生,通知观察者
* @author liyaocai
*/
void notifybservsers();
}
抽象观察者
package com.liyaocai;
/**
* 抽象观察者 .
*
* @author liyaocai
* @version V1.0
* @date 2018/8/17 15:41
* @since 1.8
*/
public interface Observer {
/**
* 更新方法,观察者根据传入的主题对象获取主题的上下文
*
* 根据传入的Object对象判断发生了何种事件
*/
void update(Observable observable, Object arg);
}
具体主题
package com.liyaocai;
import java.util.ArrayList;
import java.util.List;
/**
* 模拟Tomcat容器 .
*
* @author liyaocai
* @version V1.0
* @date 2018/8/17 15:36
* @since 1.8
*/
public class Container implements Observable {
/**
* 观察者列表
*/
private List<Observer> observers = new ArrayList<>();
@Override
public void addObsrver(Observer observer) {
observers.add(observer);
}
@Override
public void deletebserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifybservsers() {
for (Observer observer : observers) {
observer.update(this, "container start");
}
}
/**
* 容器启动方法,并且通知观察者
* @author liyaocai
* @param
* @return
* @throws
*/
public void start(){
System.out.println("container start");
notifybservsers();
}
}
具体观察者
package com.liyaocai;
/**
* 具体观察者,模拟容器监听类 .
*
* @author liyaocai
* @version V1.0
* @date 2018/8/17 15:44
* @since 1.8
*/
public class ContainerConfig implements Observer {
@Override
public void update(Observable observable, Object arg) {
String event = (String) arg;
if (event.equals("container start"))
{
System.out.println("container starting");
// do container configs
}
}
}
实际上,监听器模式也是如此,观察者(Observer)相当于事件监听者,被观察者(Observable)相当于事件源和事件,事件源经过事件的封装传给监听器,当事件源触发事件后,监听器接收到事件对象可以回调事件的方法。
Tomcat的生命周期管理
在了解了观察者模式之后,我们正式开始了解Tomcat的生命周期管理,在Tomcat的源码中,下面是相关的类:
- Lifecycle:相当于抽象主题角色,所有的容器类与组件实现类都实现了这个接口。如StandardContext
- LifecycleListener:相当于抽象观察者角色,具体的实现类有ContextConfig, HostConfig, EngineConfig类,它们在容器启动时与停止时触发。
- LifecycleEvent:生命周期事件,对主题与发生的事件进行封装。
- LifecycleSupport:生命周期管理的实用类,提供对观察者的添加,删除及通知观察者的方法。(Tomcat8.5中已经移除,使用CopyOnWriteArrayList来管理监听者集合)
- LifecycleException:生命周期异常
Lifecycle接口
Lifecycle相当于观察者模式中的抽象主题角色(Observable),它定义了添加、删除及通知管理者的方法。并且定义了13个与生命周期相关的事件,Start和stop方法是Lifecycle最重要的两个方法,分别代表启动与停止。所有四种容器的标准实现类(StandardEngine, StandardHost, StandardContext,StandardWrapper)和基本组件(Logger,Loader,Manager等)的实现类都实现了Lifecycle接口。容器启动时,主要做三件事:调用组件的启动方法,启动组件;调用子容器的启动方法,启动子容器;通知容器的观察者,使其执行相应的启动动作。子容器启动也做这三件事,这样整个Tomcat便启动了。
public interface Lifecycle {
// ----------------------------------------------------- Manifest Constants
/**
* The LifecycleEvent type for the "component before 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";
/**
* The LifecycleEvent type for the "component before start" event.
*/
public static final String BEFORE_START_EVENT = "before_start";
/**
* The LifecycleEvent type for the "component after start" event.
*/
public static final String AFTER_START_EVENT = "after_start";
/**
* The LifecycleEvent type for the "component stop" event.
*/
public static final String STOP_EVENT = "stop";
/**
* The LifecycleEvent type for the "component before stop" event.
*/
public static final String BEFORE_STOP_EVENT = "before_stop";
/**
* The LifecycleEvent type for the "component after stop" event.
*/
public static final String AFTER_STOP_EVENT = "after_stop";
/**
* The LifecycleEvent type for the "component after destroy" event.
*/
public static final String AFTER_DESTROY_EVENT = "after_destroy";
/**
* The LifecycleEvent type for the "component before destroy" event.
*/
public static final String BEFORE_DESTROY_EVENT = "before_destroy";
/**
* The LifecycleEvent type for the "periodic" event.
*/
public static final String PERIODIC_EVENT = "periodic";
/**
* The LifecycleEvent type for the "configure_start" event. Used by those
* components that use a separate component to perform configuration and
* need to signal when configuration should be performed - usually after
* {@link #BEFORE_START_EVENT} and before {@link #START_EVENT}.
*/
public static final String CONFIGURE_START_EVENT = "configure_start";
/**
* The LifecycleEvent type for the "configure_stop" event. Used by those
* components that use a separate component to perform configuration and
* need to signal when de-configuration should be performed - usually after
* {@link #STOP_EVENT} and before {@link #AFTER_STOP_EVENT}.
*/
public static final String CONFIGURE_STOP_EVENT = "configure_stop";
// --------------------------------------------------------- Public Methods
/**
* Add a LifecycleEvent listener to this component.
*
* @param listener The listener to add
*/
public void addLifecycleListener(LifecycleListener listener);
/**
* Get the life cycle listeners associated with this life cycle.
*
* @return An array containing the life cycle listeners associated with this
* life cycle. If this component has no listeners registered, a
* zero-length array is returned.
*/
public LifecycleListener[] findLifecycleListeners();
/**
* Remove a LifecycleEvent listener from this component.
*
* @param listener The listener to remove
*/
public void removeLifecycleListener(LifecycleListener listener);
/**
* Prepare the component for starting. This method should perform any
* initialization required post object creation. The following
* {@link LifecycleEvent}s will be fired in the following order:
* <ol>
* <li>INIT_EVENT: On the successful completion of component
* initialization.</li>
* </ol>
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
public void init() throws LifecycleException;
/**
* Prepare for the beginning of active use of the public methods other than
* property getters/setters and life cycle methods of this component. This
* method should be called before any of the public methods other than
* property getters/setters and life cycle methods of this component are
* utilized. The following {@link LifecycleEvent}s will be fired in the
* following order:
* <ol>
* <li>BEFORE_START_EVENT: At the beginning of the method. It is as this
* point the state transitions to
* {@link LifecycleState#STARTING_PREP}.</li>
* <li>START_EVENT: During the method once it is safe to call start() for
* any child components. It is at this point that the
* state transitions to {@link LifecycleState#STARTING}
* and that the public methods other than property
* getters/setters and life cycle methods may be
* used.</li>
* <li>AFTER_START_EVENT: At the end of the method, immediately before it
* returns. It is at this point that the state
* transitions to {@link LifecycleState#STARTED}.
* </li>
* </ol>
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
public void start() throws LifecycleException;
/**
* Gracefully terminate the active use of the public methods other than
* property getters/setters and life cycle methods of this component. Once
* the STOP_EVENT is fired, the public methods other than property
* getters/setters and life cycle methods should not be used. The following
* {@link LifecycleEvent}s will be fired in the following order:
* <ol>
* <li>BEFORE_STOP_EVENT: At the beginning of the method. It is at this
* point that the state transitions to
* {@link LifecycleState#STOPPING_PREP}.</li>
* <li>STOP_EVENT: During the method once it is safe to call stop() for
* any child components. It is at this point that the
* state transitions to {@link LifecycleState#STOPPING}
* and that the public methods other than property
* getters/setters and life cycle methods may no longer be
* used.</li>
* <li>AFTER_STOP_EVENT: At the end of the method, immediately before it
* returns. It is at this point that the state
* transitions to {@link LifecycleState#STOPPED}.
* </li>
* </ol>
*
* Note that if transitioning from {@link LifecycleState#FAILED} then the
* three events above will be fired but the component will transition
* directly from {@link LifecycleState#FAILED} to
* {@link LifecycleState#STOPPING}, bypassing
* {@link LifecycleState#STOPPING_PREP}
*
* @exception LifecycleException if this component detects a fatal error
* that needs to be reported
*/
public void stop() throws LifecycleException;
/**
* Prepare to discard the object. The following {@link LifecycleEvent}s will
* be fired in the following order:
* <ol>
* <li>DESTROY_EVENT: On the successful completion of component
* destruction.</li>
* </ol>
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
public void destroy() throws LifecycleException;
/**
* Obtain the current state of the source component.
*
* @return The current state of the source component.
*/
public LifecycleState getState();
/**
* Obtain a textual representation of the current component state. Useful
* for JMX. The format of this string may vary between point releases and
* should not be relied upon to determine component state. To determine
* component state, use {@link #getState()}.
*
* @return The name of the current component state.
*/
public String getStateName();
/**
* Marker interface used to indicate that the instance should only be used
* once. Calling {@link #stop()} on an instance that supports this interface
* will automatically call {@link #destroy()} after {@link #stop()}
* completes.
*/
public interface SingleUse {
}
}
我们来看一下具体的启动过程,
@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.
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t);
}
}
LifecycleListener接口
public interface LifecycleListener {
/**
* Acknowledge the occurrence of the specified event.
*
* @param event LifecycleEvent that has occurred
*/
public void lifecycleEvent(LifecycleEvent event);
}
LifecycleListener接口提供了一个更新方法,监听器通过事件类型来做出响应操作,与上面的示例代码的观察者模式相比(一种变形),Event封装了事件源(也就是具体主题与事件的类型)。
LifecycleEvent
我们来看一下是如何封装的,
public final class LifecycleEvent extends EventObject {
private static final long serialVersionUID = 1L;
/**
* 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;
}
/**
* The event data associated with this event.
*/
private final Object data;
/**
* The event type this instance represents.
*/
private final String type;
/**
* @return the event data of this event.
*/
public Object getData() {
return data;
}
/**
* @return the Lifecycle on which this event occurred.
*/
public Lifecycle getLifecycle() {
return (Lifecycle) getSource();
}
/**
* @return the event type of this event.
*/
public String getType() {
return this.type;
}
}
可以看出,事件封装了事件源(具体的主题)、事件的类型以及需要事件的数据。
最后总结一下:tomcat的启动过程:调用组件的启动方法,启动组件;调用子容器的启动方法,启动子容器;通知容器的观察者,使其执行相应的启动动作。每一层次的容器都这样启动,最终整个Tomcat启动完毕。
网友评论