现实生活中大部分的事物都有生命周期,就像人的生老病死一样。

在编程中也有很多对象是具有生命周期的,从初始化、运行、回收等 会经历几个不同的阶段。 在tomcat中容器相关的好多组建都实现了Lifecycle接口,当tomcat启动时,其依赖的下层组件会全部进行初始化。 并且可以对每个组件生命周期中的事件添加监听器。    好比javaee开发中经常用到的avax.servlet.ServletContextListener可以监听tomcat容器的启动于关闭,javax.servlet.ServletRequestListener可以监听一个请求的创建到销毁。 

下面开始介绍Lifecycle的设计模式。


首先是Lifecycle接口,有4中状态,分别是[启动前、启动后、关闭前、关闭后]。  并且有start()、stop()两个方法 用于启动和停止对应的对象,还有两个方法用来给该对象的生命周期事件添加监听起。

package tomcat.p5;

/**
 * @author zhoufeng
 */
public interface Lifecycle {
	
	public static final String BEFORE_START = "before_start";
	
	public static final String AFTER_START = "after_start";
	
	public static final String BEFORE_STOP = "before_stop";
	
	public static final String AFTER_STOP = "afater_stop";
	
	
	/**
	 * 添加一个监听器
	 * @param listener
	 */
	void addLifecycleListener(LifecycleListener listener);
	
	/**
	 * 获取所有的监听器
	 * @return
	 */
	LifecycleListener[] getLifecycleEvents();
	
	/**
	 * 启动
	 */
	void start();
	
	/**
	 * 停止
	 */
	void stop();
	
}

接下来看LifecycleListener接口的定义。

package tomcat.p5;

/**
 * 生命周期监听器接口
 * @author zhoufeng
 */
public interface LifecycleListener {

	/**
	 * 当被监听的对象有事件发生时 会触发该方法
	 * @param event
	 */
	public void lifecycleEvent(LifecycleEvent event); 
	
}

下面是LifecycleEvent的定义

package tomcat.p5;

/**
 * 生命周期事件
 * @author zhoufeng
 */
public class LifecycleEvent {
	
	/**
	 * 触发该事件的具体实例对象
	 */
	private Lifecycle lifecycle ;
	
	/**
	 * 事件类型(对应于Lifecycle中定义的几种状态)
	 */
	private String type ;
	
	/**
	 * 该事件携带的参数数据
	 */
	private Object data ;
	
	
	public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
		this.lifecycle = lifecycle;
		this.type = type;
		this.data = data;
	}

	public Lifecycle getLifecycle() {
		return lifecycle;
	}

	public void setLifecycle(Lifecycle lifecycle) {
		this.lifecycle = lifecycle;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}
	
	

}


由于很多对象类型都是具有生命周期的,如果每个需要生命周期的类都去实现一个Lifecycle接口实现里面的逻辑将会出现很多冗余代码, 有一种方式可以解决,就是写一个基类实现Lifecycle接口,然后其他类都基础该基类, 但是由于java单继承限制, 感觉用一个Lifecycle的实现类去作为一个父类不太合适,太局限了, 好比让“人类”继承“跑步”父类一样。

所以在tomcat里面用了一种设计模式,我也不太清楚这种设计模式叫什么名字, 先姑且叫它“伪继承组合”模式,使用一个LifecycleSupport类来管理一个Lifecycle的具体实例,并且有同名方法addLifecycleListener与getLifecycleListener,以及一个fireLifecycleListener方法来触发lifecycle的所有监听器。代码如下:

package tomcat.p5;

/**
 * @author zhoufeng
 */
public class LifecycleSupport {
	
	/**
	 * 被管理的lifecycle实例
	 */
	private Lifecycle lifecycle ;
	
	private LifecycleListener[] listeners ;

	public LifecycleSupport(Lifecycle lifecycle) {
		this.lifecycle = lifecycle;
	}
	
	public void addLifecycleListener(LifecycleListener listener){
		if(listeners == null){
			listeners = new LifecycleListener[1];
			listeners[0] = listener ;
		}else{
			 LifecycleListener[] newListeners = new LifecycleListener[listeners.length + 1];
			 newListeners[newListeners.length - 1] = listener ;
			 listeners = newListeners ;
		}
		
	}
	
	public LifecycleListener[] getLifecycleEvents(){
		return listeners ;
	}
	
	/**
	 * 触发所有的监听器
	 * @param type  事件类型
	 * @param data  
	 */
	public void fireLifecycleEvent(String type , Object data){
		if(listeners != null && listeners.length > 0){
			for (LifecycleListener lifecycleListener : listeners) {
				lifecycleListener.lifecycleEvent(new LifecycleEvent(lifecycle, type, data));  
			}
		}
	}


}


核心的几个类都实现了。  下面来写一个例子试一试,模拟一个汽车发动到停止的过程。

首先写一个汽车发动机类,该发动机也实现了Lifecycle接口 具有生命周期。 并且使用LifecycleSupport来负责管理自己的生命周期,代码如下:

package tomcat.p5.test;

import tomcat.p5.Lifecycle;
import tomcat.p5.LifecycleListener;
import tomcat.p5.LifecycleSupport;

/**
 * 汽车发动机
 * @author zhoufeng
 */
public class Engine implements Lifecycle{
	
	private LifecycleSupport lifecycle = new LifecycleSupport(this);
	

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

	@Override
	public LifecycleListener[] getLifecycleEvents() {
		return lifecycle.getLifecycleEvents();
	}

	@Override
	public void start() {
		lifecycle.fireLifecycleEvent(Lifecycle.BEFORE_START, null);
		System.out.println("发动机启动...");
		lifecycle.fireLifecycleEvent(Lifecycle.AFTER_START, null);
	}

	@Override
	public void stop() {
		lifecycle.fireLifecycleEvent(Lifecycle.BEFORE_STOP, null);
		System.out.println("发动机停止...");
		lifecycle.fireLifecycleEvent(Lifecycle.AFTER_STOP, null);
	}

	
}

下面实现一个大灯类,代码如下,同样使用LifecycleSupport管理自己的生命周期

package tomcat.p5.test;

import tomcat.p5.Lifecycle;
import tomcat.p5.LifecycleListener;
import tomcat.p5.LifecycleSupport;

/**
 * 汽车大灯
 * @author zhoufeng
 *
 */
public class Light implements Lifecycle{
	
	private LifecycleSupport lifecycle = new LifecycleSupport(this);
	
	private String name ;
	
	public Light(String name) {
		this.name = name;
	}

	@Override
	public void start() {
		lifecycle.fireLifecycleEvent(Lifecycle.BEFORE_START, null); 
		System.out.println("大灯"+ this.name +"开始发光...");
		lifecycle.fireLifecycleEvent(Lifecycle.AFTER_START, null); 
	}
	
	@Override
	public void stop() {
		lifecycle.fireLifecycleEvent(Lifecycle.BEFORE_STOP, null); 
		System.out.println("大灯"+ this.name +"关闭...");
		lifecycle.fireLifecycleEvent(Lifecycle.AFTER_STOP, null); 
	}

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

	@Override
	public LifecycleListener[] getLifecycleEvents() {
		return lifecycle.getLifecycleEvents();
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	
}

接下来就是汽车类了,里面包含了一个Engine,两个Light,注意看start()和stop()两个方法,当汽车启动时,会先将它依赖的一些组件全部启动。 停止时也一样,现将依赖的其他组件一起停止。

package tomcat.p5.test;

import tomcat.p5.Lifecycle;
import tomcat.p5.LifecycleListener;
import tomcat.p5.LifecycleSupport;

/**
 * 汽车
 * @author zhoufeng
 */
public class Car implements Lifecycle{

	private Light leftLight ; //左大灯
	private Light rightLight ; //右大灯

	private Engine engine ; //引擎

	private LifecycleSupport lifecycle = new LifecycleSupport(this);

	public void run(){
		start();
		System.out.println("桑塔拉跑起来了...");
	}

	public void shutdown(){
		stop();
		System.out.println("桑塔拉停止了...");
	}

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

	@Override
	public LifecycleListener[] getLifecycleEvents() {
		return lifecycle.getLifecycleEvents();
	}

	@Override
	public void start() {
		lifecycle.fireLifecycleEvent(Lifecycle.BEFORE_START, null);
		//先初始化其他组件
		if(engine != null && engine instanceof Lifecycle){
			((Lifecycle)engine).start();
		}
		if(leftLight != null && leftLight instanceof Lifecycle){
			((Lifecycle)leftLight).start();
		}
		if(rightLight != null && rightLight instanceof Lifecycle){
			((Lifecycle)rightLight).start();
		}

		System.out.println("桑塔拉正在启动...");
		lifecycle.fireLifecycleEvent(Lifecycle.AFTER_START, null);
	}

	@Override
	public void stop() {
		//先停止其他组件
		if(engine != null && engine instanceof Lifecycle){
			((Lifecycle)engine).stop(); 
		}
		if(leftLight != null && leftLight instanceof Lifecycle){
			((Lifecycle)leftLight).stop();
		}
		if(rightLight != null && rightLight instanceof Lifecycle){
			((Lifecycle)rightLight).stop();
		}

		lifecycle.fireLifecycleEvent(Lifecycle.BEFORE_STOP, null);
		System.out.println("桑塔拉正在停止...");
		lifecycle.fireLifecycleEvent(Lifecycle.AFTER_STOP, null);
	}

	public Light getLeftLight() {
		return leftLight;
	}

	public void setLeftLight(Light leftLight) {
		this.leftLight = leftLight;
	}

	public Light getRightLight() {
		return rightLight;
	}

	public void setRightLight(Light rightLight) {
		this.rightLight = rightLight;
	}

	public Engine getEngine() {
		return engine;
	}

	public void setEngine(Engine engine) {
		this.engine = engine;
	}

}



下面写一个入口程序来测试一下。

package tomcat.p5.test;

import tomcat.p5.Lifecycle;
import tomcat.p5.LifecycleEvent;
import tomcat.p5.LifecycleListener;

public class Startup {
	
	public static void main(String[] args) throws InterruptedException {
		
		//实例化两个灯泡
		Light leftLight = new Light(" 左 ");
		Light rightLight = new Light(" 右 ");
		
		//实例化一个发动机
		Engine engine = new Engine();
		
		//实例化一个汽车
		Car car = new Car() ;
		car.setLeftLight(leftLight);
		car.setRightLight(rightLight);
		car.setEngine(engine);
		
	
		//还可以给上面实现了Lifecycle接口的组件添加监听器
		engine.addLifecycleListener(new LifecycleListener() {
			@Override
			public void lifecycleEvent(LifecycleEvent event) {
				//只关心AFTER_START事件
				if(Lifecycle.AFTER_START.equals(event.getType())){
					System.out.println("监听到发动机启动了,轰轰轰。。。");
					//这里还可以通过event.getLifecycle()获得engin实例对象,然后做一些业务操作
				}else{
					//这里可以继续判断其他类型的事件,然后做出处理
				}
			}
		});
		
		car.addLifecycleListener(new LifecycleListener() {
			@Override
			public void lifecycleEvent(LifecycleEvent event) { 
				if(Lifecycle.AFTER_STOP.equals(event.getType())){
					System.out.println("桑塔拉快停止了,下车吧。。。");
				}
			}
		});
		
		//启动汽车
		car.run();
		
		System.out.println("\n\n\n");
		
		//模拟让桑塔拉跑3秒
		Thread.sleep(3000);
		
		//关闭汽车
		car.shutdown();
		
	}

}


输出如下

发动机启动...
监听到发动机启动了,轰轰轰。。。
大灯 左 开始发光...
大灯 右 开始发光...
桑塔拉正在启动...
桑塔拉跑起来了...




发动机停止...
大灯 左 关闭...
大灯 右 关闭...
桑塔拉正在停止...
桑塔拉停止了,下车吧。。。
桑塔拉停止了...


Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐