Coder 爱翻译 How Tomcat Works 第六章

[size=x-large]Chapter 6: Lifecycle[/size]

Catalina是由许多组件组成的。当Catalina启动时,这些组件也需要跟着启动。当Catalina停止,这些组件也必须得到被清理的机会。例如,当一个容器停止,它必须调用加载了的所有的servlet的destroy方法,session管理器必须把session对象保存到辅助存储器。一个统一的用来启动和停止组件的机制是通过实现org.apache.catalina.Lifecycle接口。

一个实现了Lifecycle接口的组件可以触发一个或许多事件:BEFORE_START_EVENT, START_EVENT, AFTER_START_EVENT, BEFORE_STOP_EVENT, STOP_EVENT和AFTER_STOP_EVENT。当通常一个启动组件时触发前三个事件,当停止组件时触发三个事件。一个事件由org.apache.catalina.LifecycleEvent类代表。最后,当然,如果一个Catalina组件想要能够触发事件,这里必须有事件监听器。事件监听器让你来处理这些事件的响应。一个监听器由org.apache.catalina.LifecycleListener接口代表。

这章将讨论Lifecycle, LifecycleEvent和LifecycleListener.

[size=large]The Lifecycle Interface[/size]

Catalina的设计允许一个组件包含其他组件。例如:一个容器可以包含像loader、manager等一样的组件。一个父组件负责启动和停止它的子组件。Catalina的设计让所有组件处于一个父组件监控下,以便一个bootstrap类只需要启动一个单独的组件就可以启动它自己以及它的子组件。这个单独的start/stop机制是通过Lifecycle接口实现的。

Listing 6.1: The Lifecycle interface

package org.apache.catalina;
public interface Lifecycle {
public static final String START_EVENT = "start";
public static final String BEFORE_START_EVENT = "before_start";
public static final String AFTER_START_EVENT = "after_start";
public static final String STOP_EVENT = "stop";
public static final String BEFORE_STOP_EVENT = "before_stop";
public static final String AFTER_STOP_EVENT = "after_stop";
public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
public void start() throws LifecycleException;
public void stop() throws LifecycleException;
}

在Lifecycle中最重要的方法是start和stop。一个组件提供这些方法的实现,所以它的父组件可以来启动可停止它。其它三个与监听器相关的方法::addLifecycleListener, findLifecycleListeners, 和removeLifecycleListener。一个组件可以有监听器。这些监听器负责监听在这个组件中的事件是否发生。当一个事件触发,监听器会处理这个响应的事件。 这六个事件的名字可以通过一个Lifecycle实例在它接口中定义的public static final Strings来触发。

[size=large]The LifecycleEvent Class[/size]

org.apache.catalina.LifecycleEvent类代表一个生命周期事件:

Listing 6.2: The org.apache.catalinaLifecycleEvent interface

package org.apache.catalina;
import java.util.EventObject;
public final class LifecycleEvent extends EventObject {
public LifecycleEvent(Lifecycle lifecycle, String type) {
this(lifecycle, type, null);
}
public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
super(lifecycle);
this.lifecycle = lifecycle;
this.type = type;
this.data = data;
}
private Object data = null;
private Lifecycle lifecycle = null;
private String type = null;
public Object getData() {
return (this.data);
}
public Lifecycle getLifecycle() {
return (this.lifecycle);
}
public String getType() {
return (this.type);
}
}


[size=large]The LifecycleListener Interface[/size]

org.apache.catalina.LifecycleListener接口代表一个生命周期监听器:

Listing 6.3: The org.apache.catalina.LifecycleListener interface

package org.apache.catalina;
import java.util.EventObject;
public interface LifecycleListener {
public void lifecycleEvent(LifecycleEvent event);
}

这个接口唯一的方法是lifecycleEvent。在一个监听器负责的事件被触发时这个方法会被调用

[size=large]The LifecycleSupport Class[/size]

一个组件实现了Lifecycle,且允许一个监听器注册它相关的事件必须提供事件处理的代码给Lifecycle接口的相关方法:addLifecycleListener, findLifecycleListeners和removeLifecycleListener。然后这个组件必须存储所有的监听器,把它们添加到一个数组或一个ArrayList或类似的对象。Catalina提供一个工具类让一个组件可以很简单地处理监听器和触发生命周期事件:org.apache.catalina.util.LifecycleSupport。

Listing 6.4: The LifecycleSupport class

package org.apache.catalina.util;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;

public final class LifecycleSupport {
public LifecycleSupport(Lifecycle lifecycle) {
super();
this.lifecycle = lifecycle;
}
private Lifecycle lifecycle = null;
private LifecycleListener listeners[] = new LifecycleListener[0];
public void addLifecycleListener(LifecycleListener listener) {
synchronized (listeners) {
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;
}
}
public LifecycleListener[] findLifecycleListeners() {
return listeners;
}
public void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
LifecycleListener interested[] = null;
synchronized (listeners) {
interested = (LifecycleListener[]) listeners.clone();
}
for (int i = 0; i < interested.length; i++)
interested[i].lifecycleEvent(event);
}
public void removeLifecycleListener(LifecycleListener listener) {
synchronized (listeners) {
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;
}
}
}

你看见LifecycleSupport类把所有的生命周期监听器存储到一个listeners的数组中,它开始是没有元素的。

private LifecycleListener listeners[] = new LifecycleListener[0];

当用addLifecycleListener方法添加一个监听器时,会创建一个新的数组。这个数组的元素大小是原数组大小的值加1。然后,原数组的所有元素会被复制到新数组中,这个新的监听器就被添加了。当使用removeLifecycleListener方法移除一个监听器时,也会创建一个新数组,这个数组的大小是原数组大小的值减1。然后,除了被移除的监听器外,其他所有元素会被复制到新数组中。

fireLifecycleEvent方法会触发一个生命周期事件。首先,它克隆监听器数组。然后,它调用数组中每一个成员的lifecycleEvent方法,并传递被触发的事件。

一个组件实现了Lifecycle可以使用LifecycleSupport类。例如, 在本章的应用中的SimpleContext类声明了下面的变量:

protected LifecycleSupport lifecycle = new LifecycleSupport(this);

要添加一个生命周期监听器,SimpleContext类调用LifecycleSupport类的addLifecycleListener方法:

public void addLifecycleListener(LifecycleListener listener) {
lifecycle.addLifecycleListener(listener);
}

要移除一个监听器,SimpleContext类调用LifecycleSupport类的removeLifecycleListener方法:

public void removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}

要触发一个事件,SimpleContext类调用LifecycleSupport类的fireLifecycleEvent方法:

lifecycle.fireLifecycleEvent(START_EVENT, null);


[size=large]The Application[/size]

本章的应用程序是建立在第五章的应用程序的基础上,它使用了Lifecycle接口和生命周期相关类型。它包含了一个context和两个wrapper,同样也有一个loader和一个mapper。本应用的这些组件都实现了Lifecycle接口,context使用了一个监听器。为了简化这个应用,我们没有使用那两个valve。下面是类图:

[img]http://dl.iteye.com/upload/attachment/360948/a967fb42-d66c-3b0d-9eb2-454515a5a794.jpg[/img]

注意SimpleContextLifecycleListener类代表SimpleContext类的一个监听器类。SimpleContextValve, SimpleContextMapper和SimpleWrapperValve类同第五章的是一样的。

[size=large]ex06.pyrmont.core.SimpleContext[/size]

本应用的SimpleContext类除了实现了Lifecycle接口,其他和第五章的相似。SimpleContext类使用下面的变量引用一个LifecycleSupport实例:

protected LifecycleSupport lifecycle = new LifecycleSupport(this);

它也用一个叫做started的boolean变量,这个变量表明SimpleContext实例是否启动了。SimpleContext类提供了Lifecycle接口方法的实现。

Listing 6.5: Methods from the Lifecycle interface.

public void addLifecycleListener(LifecycleListener listener) {
lifecycle.addLifecycleListener(listener);
}
public LifecycleListener[] findLifecycleListeners() {
return null;
}
public void removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}
public synchronized void start() throws LifecycleException {
if (started)
throw new LifecycleException("SimpleContext has already started");
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
started = true;
try {
// Start our subordinate components, if any
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start();

// Start our child containers, if any
Container Children[] = findChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Lifecycle)
((Lifecycle) children[i]).start();
}

// Start the Valves in our pipeline (including the basic),
// if any
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();
// Notify our Interested LifecycleListeners
lifecycle.firelifecycleEvent(START_EVENT, null);
}
catch (Exception e) {
e.printStackTrace();
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}

public void stop() throws LifecycleException {
if (!started)
throw new LifecycleException("SimpleContext has not been started");
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
try {
// Stop the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle) (
((Lifecycle) pipeline).stop();
}
// Stop our child containers, if any
Container children[] = findChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Lifecycle)
((Lifecycle) children[i]).stop();
}
if ((loader != null) && (loader instanceof Lifecycle)) {
((Lifecycle) loader).stop();
}
} catch (Exception e) {
e.printStackTrace();
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
}

注意start方法是怎么来启动所有的像:Loader、Pipeline、Mapper这样的子容器和与它的相关组件,而stop方法又是怎么来停止它们的呢?使用这种机制来启动容器模块的所有组件,你只需要启动在层次结构中最高层的组件(本例中是SimpleContext实例)。要停止它们,你只需要停止同样的这个单独组件。

在SimpleContext中的start方法的开始要通过检查它是否启动,如果这个组件在之前已经启动了,这时将抛一个LifecycleException异常。

if (started)
throw new LifecycleException( "SimpleContext has already started");

它然后触发BEFORE_START_EVENT事件。

// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);

结果,每一个在SimpleContext实例里注册的相关事件监听器将被调用。在这个应用中,一个SimpleContextLifecycleListener类型的监听器注册它的相关事件。

接下来,start方法把started的这个boolean变量设置成true,表明组件被启动了。

started = true;

然后start方法启动所有组件和它的子容器。当前这里有两个组件,它们都实现了Lifecycle接口。SimpleLoader和SimplePipeline。SimpleContext有两个wrapper作为它的子容器。这两个都是SimpleWrapper类型,它们也都实现了Lifecycle接口。

try {
// Start our subordinate components, if any
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start();
// Start our child containers, if any
Container children[] = findChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Lifecycle)
((Lifecycle) children[i]).start();
}
// Start the Valves in our pipeline (including the basic),
// if any
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();

当所有组件和子容器都启动后,start方法触发这两事件:START_EVENT和 AFTER_START_EVENT.。

// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(START_EVENT, null);
.
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

这个stop方法首先检查这个实例是否启动了,如果没启动,它抛出一个LifecycleException异常。

if (!started)
throw new LifecycleException( "SimpleContext has not been started");

它然后触发BEFORE_STOP_EVENT 和STOP_EVENT这两个事件,并设置started这个boolean变量。

// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;

接下来,stop方法停止它所有相关组件和SimpleContext实例的子容器。

try {
// Stop the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).stop();
}
// Stop our child containers, if any
Container children[] = findChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Lifecycle)
((Lifecycle) children[i]).stop();
}
if ((loader != null) && (loader instanceof Lifecycle)) {
((Lifecycle) loader).stop();
}
}

最后,触发AFTER_STOP_EVENT事件。

// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);


[size=large]ex06.pyrmont.core.SimpleContextLifecycleListener[/size]

SimpleContextLifecycleListener类代表一个SimpleContext接口的监听器:

Listing 6.6: The SimpleContextLifecycleListener class

package ex06.pyrmont.core;
import org.apache.catalina.Context;
import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;

public class SimpleContextLifecycleListener implements LifecycleListener {

public void lifecycleEvent(LifecycleEvent event) {
Lifecycle lifecycle = event.getLifecycle();
System.out.println("SimpleContextLifecycleListener's event " + event.getType().toString());
if (Lifecycle.START_EVENT.equals(event.getType())) {
System.out.println("Starting context.");
}
else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
System.out.println("Stopping context.");
}
}
}

SimpleContextLifecycleListener类的lifecycleEvent方法的实现很简单。它只是简单打印被触发的事件。如果它是一个START_EVENT事件,lifecycleEvent方法打印启动上下文(Starting context)。如果事件是一个STOP_EVENT事件它打印停止上下文(Stopping context)。

[size=large]ex06.pyrmont.core.SimpleLoader[/size]

SimpleLoader类除了实现了Lifecycle接口外,其它的和第五章的类似。Lifecycle接口的方法实现就是在控制台打印字符串。更重要的是,通过实现Lifecycle接口,一个SimpleLoader实例可以通过它的相关容器来启动它。
在SimpleLoader的Lifecycle接口的这些方法:

Listing 6.7: The methods from Lifecycle in the SimpleLoader class

public void addLifecycleListener(LifecycleListener listener) { }
public LifecycleListener[] findLifecycleListeners() {
return null;
}
public void removeLifecycleListener(LifecycleListener listener) { }
public synchronized void start() throws LifecycleException {
System.out.println("Starting SimpleLoader");
}
public void stop() throws LifecycleException { }


[size=large]ex06.pyrmont.core.SimplePipeline[/size]

除了实现了Pipeline接口,SimplePipeline类也实现了Lifecycle接口。Lifecycle接口方法的实现是空的,但是现在这个类的实例可以被它相关联的容器来启动。类其它部分跟第五章的SimplePipeline类相同。

[size=large]ex06.pyrmont.core.SimpleWrapper[/size]

这个类和ex05.pyrmont.core.SimpleWrapper类相似。在这个应用,它实现了Lifecycle接口,所以它可以被它的父容器启动。在这个应用程序大多数方法除了start和stop方法,其它方法的实现都为空。

Listing 6.8: The methods from the Lifecycle interface

public void addLifecycleListener(LifecycleListener listener) { }
public LifecycleListener[] findLifecycleListeners() {
return null;
}
public void removeLifecycleListener(LifecycleListener listener) ( }
public synchronized void start() throws LifecycleException {
System.out.println("Starting Wrapper " + name);
if (started)
throw new LifecycleException("Wrapper already started");
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
started = true;
// Start our subordinate components, if any
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start();
// Start the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(START_EVENT, null);
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
public void stop() throws LifecycleException {
System.out.println("Stopping wrapper " + name);
// Shut down our servlet instance (if it has been initialized)
try {
instance.destroy();
} catch (Throwable t) {
}
instance = null;
if (!started)
throw new LifecycleException("Wrapper " + name + " not started");
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
// Stop the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).stop();
}
// Stop our subordinate components, if any
if ((loader != null) && (loader instanceof Lifecycle)) {
((Lifecycle) loader).stop();
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);
}


SimpleWrapper的start方法和SimpleContext类的start方法类似。它启动任何添加到它里面的组件。触发BEFORE_START_EVENT, START_EVENT和AFTER_START_EVENT事件。

SimpleWrapper的stop方法更有趣。打印了一个简单的字符串后,它调用servlet实例的destroy方法。

System.out.println("Stopping wrapper " + name);
// Shut down our servlet instance (if it has been initialized)
try {
instance.destroy();
} catch (Throwable t) {
}
instance = null;

然后,检查wrapper是否启动了,如果没有,它抛出一个LifecycleException异常。

if (!started)
throw new LifecycleException("Wrapper " + name + " not started");

接下来,它触发BEFORE_STOP_EVENT和STOP_EVENT事件。然后设置started这个boolean变量。

// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, null);
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;

接下来,它停止loader和pipeline相关的组件。在这个应用程序,SimpleWrapper实例没有loader。

// Stop the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).stop();
}
// Stop our subordinate components, if any
if ((loader != null) && (loader instanceof Lifecycle)) {
((Lifecycle) loader).stop();
}

最后,它触发 AFTER_STOP_EVENT事件。

// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, null);


总结:这章你知道了怎么与Lifecycle接口工作。这个接口定义了一个组件的生命周期和提供了优雅的方式来发送事件给另一个组件。此外,Lifecycle接口也使得使用一个单独的start/stop来启动和停止在Catalina的所有组件变得可能。

第六章 完
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值