`
kanny87929
  • 浏览: 17054 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

再读Tomcat5.5下的‘观察者模式’

阅读更多
最近我正在根据《How Tomcat Works》这本书的讲解,阅读Tomcat 7的源码
但这本书的源码讲解基于Tomcat 4
讲到第5章:关于Tomcat4的生命周期的时候
我就看不大明白Tomcat 7的源码,于是我从Apache Tomcat网站又下载了Tomcat 5.5的源码
进一步了解这一章,这一章讲的就是Tomcat的生命周期Lifecycle,其中最主要的就是利用了
设计模式中相当经典的模式:观察者模式。

现在推荐一下相关文章和相关类图,学习设计模式而不去看类图或是看不懂,那是相当大的一个阻碍。
1.
标题:《设计模式之:解剖观察者模式》
网址:http://www.iteye.com/topic/102068
内容:从最基础的方面剖析了'观察者模式'
发表时间:2007-07-17(相当的早,我还没出道就发布了...)
类图:



2.
标题:《Tomcat源码---容器生命周期管理(Lifecycle)一》
网址:http://wuquanyin1011.iteye.com/blog/628993
内容:从源码上讲到了‘观察者模式’的运用,这也就是我文章题目只能写再读了,人家都分析过了...
发表时间:2010-03-31
类图:



3.
标题:《Tomcat 系统架构与设计模式,第 2 部分: 设计模式分析》
网址:http://www.ibm.com/developerworks/cn/java/j-lo-tomcat2/
内容:讲解了Tomcat中几个最重要的模式,但这是第2部分的内容,大家也要看一下第1部分的内容
发表时间:2010-05-27
类图:




如果是新接触观察者模式或是还没深入理解观察者模式的朋友一定要看推荐的第一篇文章。这样下面的东西就好理解。

以下都是Tomcat5.5的相关源码,而在Tomcat 7中又增添了新的接口和类来管理生命周期。
这里我把Tomcat构建观察者模式来处理Tomcat生命周期的所有相关类和接口都抽了出来
删除了不必要的类和代码,因为我们只是为了要探究下观察者模式。

其中有以下类和接口:(上面的相关类图对帮助理解这6个类和接口之间的依赖关系是非常有帮助的,所以我先贴出了类图)
Lifecycle.java:抽象被观察者
StandardServer.java :具体被观察者(这个类是Tomcat5.5下实现的众多具体被观察者中的一个)
LifecycleListener.java : 抽象观察者
ServerLifecycleListener.java : 具体观察者(这个类是Tomcat5.5下实现的众多具体观察者中的一个)
这里还要提下:在Tomcat 7中,具体被观察者和具体观察者中的功能都被抽出来统一管理
LifecycleSupport.java :具体被观察者的代理类,为了把所有具体被观察者的共同操作统一管理(在推荐第2篇文章中那哥们说这里用了‘适配器模式’)
LifecycleEvent.java :事件类

下面根据顺序放出各个类的具体实现代码

Lifecycle.java:抽象被观察者


package demo.tomcat5.lifecycle;
//抽象被观察者
public interface Lifecycle {
	
   //抽象被观察者中定义的各种事件
    public static final String INIT_EVENT = "init";
    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 static final String DESTROY_EVENT = "destroy";
    public static final String PERIODIC_EVENT = "periodic";
    
    //添加一个观察者去观察被观察者
    public void addLifecycleListener(LifecycleListener listener);
    
    //列出一个被观察者上的所有观察者
    public LifecycleListener[] findLifecycleListeners();
    
    //删除一个被观察者上的指定观察者
    public void removeLifecycleListener(LifecycleListener listener);

    public void start();
    public void stop();
}


StandardServer.java :具体被观察者
package demo.tomcat5.lifecycle;
//具体被观察者
public final class StandardServer implements Lifecycle {
	
	//把当前具体被观察者交给被观察者支持类,由它来代理实现添加、删除、查找观测者的操作
	//具体被观察者只要启动业务,然后在启动业务后根据业务事件的状态来激活观察者做相应操作
	private LifecycleSupport lifecycle = new LifecycleSupport(this);
	
	public void addLifecycleListener(LifecycleListener listener) {

		lifecycle.addLifecycleListener(listener);
	}

	public LifecycleListener[] findLifecycleListeners() {
		
		return lifecycle.findLifecycleListeners();
	}

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

	public void start() {

        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, "Server 启动前我们干什么呢?也许我们要初始化一些配置信息");
        
        lifecycle.fireLifecycleEvent(START_EVENT, "Server 启动中我们干什么呢?也许我们要添加Service到Server中");
        
        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, "Server 启动后我们干什么呢?不知道了");
	}

	public void stop() {
		
        lifecycle.fireLifecycleEvent(BEFORE_STOP_EVENT, "... Server 停止前");

        lifecycle.fireLifecycleEvent(STOP_EVENT, "... Server 停止中");
      
        lifecycle.fireLifecycleEvent(AFTER_STOP_EVENT, "... Server 停止后");
	}

}


LifecycleListener.java : 抽象观察者
package demo.tomcat5.lifecycle;
//抽象观察者
public interface LifecycleListener {
	public void lifecycleEvent(LifecycleEvent event);
}


ServerLifecycleListener.java : 具体观察者
package demo.tomcat5.lifecycle;

//具体观察者类
public class ServerLifecycleListener implements LifecycleListener {

	public void lifecycleEvent(LifecycleEvent event) {

		if (Lifecycle.BEFORE_START_EVENT.equals(event.getType())) {

			System.out.println(event.getData().toString());

		} else if (Lifecycle.START_EVENT.equals(event.getType())) {

			System.out.println(event.getData().toString());

		} else if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {

			System.out.println(event.getData().toString());

		} else if (Lifecycle.BEFORE_STOP_EVENT.equals(event.getType())) {
			
			System.out.println(event.getData().toString());
			
		} else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
			
			System.out.println(event.getData().toString());
			
		} else if (Lifecycle.AFTER_STOP_EVENT.equals(event.getType())) {
			
			System.out.println(event.getData().toString());
			
		}
	}

}



LifecycleSupport.java :具体被观察者的代理类
package demo.tomcat5.lifecycle;
//具体被观察者代理类
public final class LifecycleSupport {

	private Lifecycle lifecycle = null;
	
	public LifecycleSupport(Lifecycle lifecycle) {
		super();
		this.lifecycle = lifecycle;
	}
	//定义一个观察者数组,就是为了维护在这个具体被观察者上的所有观察者。
	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) {
			//这里是我唯一不解的地方,为什么要用副本。
			//当然这只是tomcat5.5的实现,在tomcat7中这个步骤被删除了
			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;
		}

	}
}



LifecycleEvent.java :事件类
package demo.tomcat5.lifecycle;

import java.util.EventObject;
//事件类
public final class LifecycleEvent extends EventObject {

	private static final long serialVersionUID = 1L;

	private Object data = null;
	private Lifecycle lifecycle = null;
	private String type = null;

	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;

	}

	public Object getData() {

		return (this.data);

	}

	public Lifecycle getLifecycle() {

		return (this.lifecycle);

	}

	public String getType() {

		return (this.type);

	}
}



最后我在提供‘推荐第一篇文章’和‘本文’的源代码供同学们学习
  • 大小: 8.6 KB
  • 大小: 4 KB
  • 大小: 13.4 KB
分享到:
评论
24 楼 kanny87929 2011-04-08  
tianlovv 写道
讲的不错,也计划着要看tomcat源码了,LZ这么一讲让我对研究tomcat源码兴趣大增,哈哈!关于为什么clone数组那,我想到有两点
1  保证了数组的不变性,其它线程对数组操作与这个副本无关
2  缩小同步代码块。因为可以把执行业务操作也放在同步块中,这样不需要clone了,但通常业务操作是比较占用时间的,这样会影响性能
问一下tomcat7中是用什么容器装载元素的



应该说,tomcat 7是用什么数据结构来存储元素的更专业...
tomcat 7中就是直接操作数组,把复制出副本这个操作给删除了。
23 楼 tianlovv 2011-04-08  
讲的不错,也计划着要看tomcat源码了,LZ这么一讲让我对研究tomcat源码兴趣大增,哈哈!关于为什么clone数组那,我想到有两点
1  保证了数组的不变性,其它线程对数组操作与这个副本无关
2  缩小同步代码块。因为可以把执行业务操作也放在同步块中,这样不需要clone了,但通常业务操作是比较占用时间的,这样会影响性能
问一下tomcat7中是用什么容器装载元素的
22 楼 kanny87929 2011-04-07  
wujianjun0410 写道
好文章,学习了  

谢支持,不要光看头像,头像是我老婆
21 楼 wujianjun0410 2011-04-07  
好文章,学习了  
20 楼 liuxuejin 2011-04-07  
正在看,希望lz多点出tomcat的文章!
19 楼 kanny87929 2011-04-07  
没有太多的建议就是看
how tomcat works
这书学,当然一定要有基础
对java的模式有个大概理解

那么看的时候就轻松很多

以后看到有用的东西会陆续发上来
18 楼 sebatinsky 2011-04-06  
呵呵,先学习一下。。。
17 楼 esanone 2011-04-06  
catalia设计的很组件化,完全可以对感兴趣的组件进行学习。
16 楼 whao189 2011-04-06  
想去看看 tomcat 这个本书, 楼主给点捷径!
15 楼 amwiacel 2011-04-06  
kanny87929 写道
amwiacel 写道
我是看了一半,那英文....有些就懂了,有些就不懂,还有些就模糊的...

我看的中文

哪有中文版,可以告诉吗?
14 楼 houyanhuasong 2011-04-06  
过完年的时候,公司事情不多,不忙,看了一点。。。希望能多点讲解的给我们指指路
13 楼 kanny87929 2011-04-06  
風一樣的男子 写道
kanny87929 写道
amwiacel 写道
我是看了一半,那英文....有些就懂了,有些就不懂,还有些就模糊的...

我看的中文


中文的不全吧?
看到7/8 没再往下看
时间分配问题


这个不清楚,不过看的明白,能深入理解就好
12 楼 風一樣的男子 2011-04-06  
kanny87929 写道
amwiacel 写道
我是看了一半,那英文....有些就懂了,有些就不懂,还有些就模糊的...

我看的中文


中文的不全吧?
看到7/8 没再往下看
时间分配问题
11 楼 kanny87929 2011-04-06  
amwiacel 写道
我是看了一半,那英文....有些就懂了,有些就不懂,还有些就模糊的...

我看的中文
10 楼 tracyhuyan 2011-04-06  
正在看第二章...
9 楼 amwiacel 2011-04-06  
我是看了一半,那英文....有些就懂了,有些就不懂,还有些就模糊的...
8 楼 kanny87929 2011-04-06  
...是不是因为你看不懂才坚持不下去
7 楼 jakehuu 2011-04-06  
这本书 我看到一半 没有坚持下去
6 楼 longxiaoyan 2011-04-06  
我也正打算看这本书。
5 楼 kanny87929 2011-04-06  
我觉得这章的内容非常的重要,所以很有必要一遍再一遍的讲

相关推荐

Global site tag (gtag.js) - Google Analytics