设为首页 收藏本站
查看: 1037|回复: 0

[经验分享] Coder 爱翻译 How Tomcat Works 第六章

[复制链接]

尚未签到

发表于 2017-2-8 09:03:11 | 显示全部楼层 |阅读模式
Chapter 6: Lifecycle
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.
The Lifecycle Interface
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来触发。
The LifecycleEvent Class
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);
}
}


The LifecycleListener Interface
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。在一个监听器负责的事件被触发时这个方法会被调用
The LifecycleSupport Class
一个组件实现了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 = listeners;
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.lifecycleEvent(event);
}
public void removeLifecycleListener(LifecycleListener listener) {
synchronized (listeners) {
int n = -1;
for (int i = 0; i < listeners.length; i++) {
if (listeners == 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;
}
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);


The Application
本章的应用程序是建立在第五章的应用程序的基础上,它使用了Lifecycle接口和生命周期相关类型。它包含了一个context和两个wrapper,同样也有一个loader和一个mapper。本应用的这些组件都实现了Lifecycle接口,context使用了一个监听器。为了简化这个应用,我们没有使用那两个valve。下面是类图:
DSC0000.jpg
注意SimpleContextLifecycleListener类代表SimpleContext类的一个监听器类。SimpleContextValve, SimpleContextMapper和SimpleWrapperValve类同第五章的是一样的。
ex06.pyrmont.core.SimpleContext
本应用的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 instanceof Lifecycle)
((Lifecycle) children).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 instanceof Lifecycle)
((Lifecycle) children).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 instanceof Lifecycle)
((Lifecycle) children).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 instanceof Lifecycle)
((Lifecycle) children).stop();
}
if ((loader != null) && (loader instanceof Lifecycle)) {
((Lifecycle) loader).stop();
}
}

最后,触发AFTER_STOP_EVENT事件。

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


ex06.pyrmont.core.SimpleContextLifecycleListener
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)。
ex06.pyrmont.core.SimpleLoader
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 { }


ex06.pyrmont.core.SimplePipeline
除了实现了Pipeline接口,SimplePipeline类也实现了Lifecycle接口。Lifecycle接口方法的实现是空的,但是现在这个类的实例可以被它相关联的容器来启动。类其它部分跟第五章的SimplePipeline类相同。
ex06.pyrmont.core.SimpleWrapper
这个类和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的所有组件变得可能。
                                                                       第六章 完

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-339023-1-1.html 上篇帖子: Coder 爱翻译 How Tomcat Works 第五章 第二部分 下篇帖子: 《How Tomcat Works》翻译(4)之 生命周期
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表