tomcat源码分析二
在这一篇中,看下观察者模式的应用。首先来看下观察者模式的概念:观察者模式是一种一对多的关系,多个观察者对象同时关注一个主题对象。观察者模式中有主题对象和观察者对象,我们可以把球赛比作一个观察者模型,那么球赛就是主题对象,观众就是观察者对象。以下通过java语言对观察者,java.util.Observable的应用实现,观察者在tomcat源代码中的应用,三个部分来阐述观察者模式。一. java语言中的观察者模式
通过java.util.Observable,首先来看下其源代码。
//观察者接口
public interface Observer {
void update(Observable o, Object arg);
}
//主题对象
public class Observable {
private boolean changed = false;//状态变量
//维护观察者对象的集合
private Vector obs;
public Observable() {
obs = new Vector();
}
//将观察者加入到集合中
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
//从集合中删除观察者
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
//通知
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed) return;
arrLocal = obs.toArray();//将结合转化成数组
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal).update(this, arg);//观察者作出状态改变的操作
}
//状态的几个相关方法
protected synchronized void setChanged() {
changed = true;
}
protected synchronized void clearChanged() {
changed = false;
}
public synchronized boolean hasChanged() {
return changed;
}
二.java.util.Observable的应用实现
上一部分是java源代码中对于观察者模式的实现,对代码有注释。如果不明白的话,可以结合下面的一个例子来看,就应该很清楚了。个人觉得以下的例子(来自网上)比《设计与模式》一书中的例子更直观些,商品为主题对象,对于商品的价格和名称的改变有相应的观察者。
主题对象
public class Product extends Observable{
private String name;
private float price;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
//设置观察点(changed=true )
setChanged();
//观察者作出相应的改变
notifyObservers(name);
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
//设置观察点,同上
setChanged();
notifyObservers(price);
}
}
观察者对象
//商品名称观察者类
public class NameObserver implements Observer{
private String name = "";
//源代码中对应((Observer)arrLocal).update(this, arg)
public void update(Observable ob, Object arg) {
if(arg instanceof String){
name = (String)arg;
System.out.println("name has been changed to:"+name);
}
}
}
//价格观察者类
public class PriceObserver implements Observer{
private float price;
//同上
public void update(Observable ob, Object arg) {
if(arg instanceof Float){
price = (Float)arg;
System.out.println("name has been changed to:"+price);
}
}
}
运行看下效果
public static void main(String[] args) {
Product p1 = new Product();
NameObserver nameObserver = new NameObserver();
PriceObserver priceObserver = new PriceObserver();
p1.addObserver(nameObserver);
p1.addObserver(priceObserver);
p1.setName("苹果");
p1.setPrice(8);
p1.setName("香蕉");
}
三. tomcat中观察者的实现
结合源代码的分析以及一个实例,应该对于观察者模式有一定的理解了,接下来看下在tomcat的源代码中的使用。
(1)主题接口LifeCycle,在其中定义了状态变量init,start…等的状态,看下源代码对于该接口的定义。
//增加观察者
public addLifecycleListener(LifecycleListener listener);
//获取所有的观察者
public LifecycleListener[] findLifecycleListeners();
//移除观察者
public void removeLifecycleListener(LifecycleListener listener);
//其他2个方法
public void start() throws LifecycleException;
public void stop() throws LifecycleException;
(2)观察者接口 LifecycleListener的定义
//主题变化时候,要执行的方法
public void lifecycleEvent(LifecycleEvent event);
(3) 有大量类实现了主题LifeCycle接口,作为取其中的StandardServer来分析,看下是怎么用的。
由于在StandardServer中用到了LifeCycleSupport,所以先分析下该类。
public final class LifeCycleSupport{
//构造器
public LifeCycleSupport (Lifecycle lifecycle) {
super();
this.lifecycle = lifecycle;
}
//存储观察者的数组,看Lifecycle就会发现。里面有一个findLifecycleListeners获取数组,但是没有定义数组变量。
private LifecycleListener listeners[] = new LifecycleListener;
//将观察者对象放入到数组中,此处定义直接每次增加的时候,定义一个数目加1的数据。是出于性能的考虑,这种方式可以在编程中运用。在tomcat中可以看到大量类似的编程方式有些是用System.arraycopy来处理.
public void addLifecycleListener(LifecycleListener listener) {
synchronized (listenersLock) {
LifecycleListener results[] =
new LifecycleListener;
for (int i = 0; i < listeners.length; i++)
results = listeners;
results = listener;
listeners = results;
}
}
public LifecycleListener[] findLifecycleListeners() {
return listeners;
}
public void removeLifecycleListener(LifecycleListener listener) {
lifecycle.removeLifecycleListener(listener);
}
public void fireLifecycleEvent(String type, Object data) {
if (Lifecycle.INIT_EVENT.equals(type)) {
state = "INITIALIZED";
}//此处省略部分else if 语句
LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
LifecycleListener interested[] = listeners;
for (int i = 0; i < interested.length; i++)
interested.lifecycleEvent(event);//有改变后观察者进行处理
}
}
(4)看了LifeCycleSupport的实现,再看下StandardServer中的实现就很清楚了。该类中lifecycle的方法全部是调用LifeCycleSupport。这里是对观察者之上有进一步的处理。
public final class StandardServer
implements LifeCycle, Server, MBeanRegistration
//这里看下LifeCycle接口中的几个方法的实现
private LifeCycleSupport lifeCycle = new LifeCycleSupport(this);
public void addLifeCycleListener(LifeCycleListener listener) {
lifeCycle.addLifeCycleListener(listener);
}
public LifecycleListener[] findLifecycleListeners() {
return lifecycle.findLifecycleListeners();
}
public void start() throws LifecycleException {
// Validate and update our current component state
if (started) {
log.debug(sm.getString("standardServer.start.started"));
return;
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// Start our defined Services
synchronized (services) {
for (int i = 0; i < services.length; i++) {
if (services instanceof Lifecycle)
((Lifecycle) services).start();
}
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
(5)LifecycleEvent这个类,是将数据封装在一个对象中。
在org.apache.catalina.mbeans.ServerLifecycleListener中可以看到,对于观察者在不同状态下的实现代码。
文字编译器不好用,莫名奇妙的多了很多空的java代码框。
页:
[1]