Tomcat Lifecycle 观察者模式

前言

Pipeline 和 Lifecycle 贯穿Tomcat 整个源码,上一篇中博客已经介绍了 Pipeline。接下来介绍 Lifecycle。Lifecycle 是整个 Tomcat 观察者设计模式思想的体现。我们已经知道 Tomcat 被分为4层,Engine 层, Host 层,Context 层和 Wrapper 层,层层嵌套。Engine 层是整个 Tomcat 的 Servlet 引擎,位于最高层。 Context 层上一层是 Host 层,一个Host 层可以包括多个 Context,一个Context 就是一个应用。当 Tomcat 要部署多个应用(Context),就要需要主机(Host)来管理了。Context 层则又可以有多个 Wrapper 层,一个 Wrapper 对应着一个 Servlet。在这层级分明的架构中,管道 Pileline 用于执行每层的流水线任务,并一层一层按顺序执行下去,这些流水线任务一般用于 Tomcat 对接收到的请求做一些处理。而 Lifecycle 则一般是 Tomcat 启动时,通知对每一层初始化开始前,开始中和开始后这些事件监听的观察者,观察者对自己关心的事件作出反应。当然 Lifecycle 并不仅仅应用于 Tomcat 的启动初始化过程,只是 Tomcat 初始化是 Lifecycle 观察者设计模式很重要的应用。

概念

  • 被观察者:相当于报社,都有事件发生时,把事件通知给订阅报纸的人。
  • 观察者:相当于报社报刊的订阅者,接收报社发送过来的事件。当事件与自己有关时,做出反应。
  • 通知:对事件的封装。由被观察者发送给观察者。

在 Tomcat 中,每一个被观察者都实现了 Lifecycle 接口, Lifecycle 接口定义了一些添加或者移除观察者的方法和一些事件名称。每一个观察者则都实现了 LifecycleListener 接口,LifecycleListener 接口定义了对事件作出反应的方法。被观察者向观察者发送的通知,即事件的封装,都由 LifecycleEvent 类进行封装,它是 final 类型的,即无法继承,所以所有的通知都由 LifecycleEnvent 封装。下面是这3个类的 UML 图。

实现

上一篇 Pipeline 中以 Context 和 Wrapper 为例讲解,这里就以 Engine 层和 Host 层为例进行讲解,同 Pipeline 一样,每一层的 Lifecycle 实现基本是一个套路,明白了 Engine 和 Host,自然也就明白了 Context 和 Engine 层的 Lifecycle 实现。跟 Context 和 Wrapper 一样,Host 和 Engine 的标准实现是 StandardEngine 和 StandardHost。这两个类中都有一个 LifecycleSupport lifecycle = new LifecycleSupport(this)对象,这个 LifecycleSupprot 对象是干什么的呢?按照单一权责原则,StandardEngine 和 StandardHost 类将观察自己的对象委托给了 LifecycleSupport 对象进行管理。所以,在 LifecycleSupport 类中,有一个 LifecycleListener 类型的数组来保存所有的观察者。在 StandardHost 和 StandardEngine 添加观察者,最后都保存在这个数组中。当 Tomcat 启动时候,StandardEngine 的 start() 被调用来初始化 Engine 层。StandardEngine 的 start() 方法执行部分初始化工作后,会调用父类 Container 的start() 方法。来看看 Container 这个 Start() 方法的代码。

public synchronized void start() throws LifecycleException {
    .....
    lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);

    .....
    Container children[] = findChildren();
    for (int i = 0; i < children.length; i++) {
        if (children[i] instanceof Lifecycle)
                ((Lifecycle)
           children[i]).start();
    }

    lifecycle.fireLifecycleEvent(START_EVENT, null);

     ....

     lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

}

lifecycle 就是 LifecycleSupport 对象。下面是 LifecycleSupport 的 fireLifecycleEvent 方法代码。

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[i].lifecycleEvent(event);

    }

(注意,这里面的 lifecycle 是被观察的对象,即 StandardEngine,不要和上面的弄混淆了。)fireLifecycleEvent() 把事件封装成了 LifecycleEvent 对象,然后遍历 LifecycleListener 数组,即遍历观察者,将封装的事件发送给每一个观察者。下面是我自定义的一个观察者对象。

public class SimpleEngineConfig implements LifecycleListener {

  public void lifecycleEvent(LifecycleEvent event) {
    if (Lifecycle.START_EVENT.equals(event.getType())) {
      System.out.println("收到开始初始化事件通知");
    }
  }
}

当我把这个观察者对象在 StandardEngine 中注册,保存在 LifecycleSupport 的观察者数组中,这样当 StandardEngine 的start() 方法执行lifecycle.fireLifecycleEvent(START_EVENT, null);是,就会输出收到开始初始化事件通知
在回头看看 StandardEngine 的start() 方法。前面介绍 Engine 层下面包含着 Host 层,所以Container children[] = findChildren(); 就会得到 StandardHost 对象,然后调用 StandardHost 的 start() 方法。

public synchronized void start() throws LifecycleException {
        ....

        super.start();

    }

StandardHost 的 start() 方法同样调用父类的 start() 方法。当你看 Tomcat 源码的时候,你会发现 Engine , Host, Context,Wrapper 都继承同一个父类 Container。也就是每一层的start() 方法最后都会调用父类的 start()方法,父类相同,所以它们对自己的观察者发送通知模式时一模一样的。看懂了 StrandardEngine 的 Lifecycle 观察者模式实现,其它层也就自然懂了!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值