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

[经验分享] tomcat源码分析二

[复制链接]

尚未签到

发表于 2017-1-25 10:16:11 | 显示全部楼层 |阅读模式
         在这一篇中,看下观察者模式的应用。首先来看下观察者模式的概念:观察者模式是一种一对多的关系,多个观察者对象同时关注一个主题对象。观察者模式中有主题对象和观察者对象,我们可以把球赛比作一个观察者模型,那么球赛就是主题对象,观众就是观察者对象。以下通过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的源代码中的使用。
DSC0000.jpg

  (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[0];
//将观察者对象放入到数组中,此处定义直接每次增加的时候,定义一个数目加1的数据。是出于性能的考虑,这种方式可以在编程中运用。在tomcat中可以看到大量类似的编程方式有些是用System.arraycopy来处理.
public void addLifecycleListener(LifecycleListener listener) {
synchronized (listenersLock) {
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 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、欢迎大家加入本站运维交流群:群②: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-333194-1-1.html 上篇帖子: TOMCAT中的SOAP简单应用 下篇帖子: Tomcat 表单乱码解决办法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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