Tomcat源码分析--生命周期管理

来源:互联网 发布:万界淘宝商txt百度云 编辑:程序博客网 时间:2024/05/16 08:02

概述

大致了解Tomcat整体架构后,会发现Tomcat整体都是以组件的形式组织的,并且各组件之间具有包含和被包含的关系,Server组件包含Servevice,serveice包含Engine等等,下面用一张图说明Tomcat各组件之间的这种包含和被包含关系。

这里写图片描述

(图片来源: http://www.cnblogs.com/diegodu/p/5915300.html)

图片很清楚的说明了各组件之间的关系,那么问题来了:

这么多的组件该怎么组织呢?Tomcat的整个初始化和启动不可能一个一个组件init和start吧,那样不仅会造成代码逻辑混乱和组件遗漏,而且也不利于后期的功能拓展。基于此等考虑,Tomcat使用了一套完整的生命周期管理机制,把整个组件逻辑当做树来处理,每个子组件的初始化和启动等操作都交由其父组件来完成,这样我们只需要操作根组件就行了。

实现设计

概述

下面是生命周期的设计图:

这里写图片描述

生命周期最基础的实现就是上面这几个,即LifecycleState,Lifecycle,LifecycleListener,
LifecycleEvent和LifecycleSupport这几个类,枚举和接口

具体实现

  • Lifecycle接口

    作为事件源接口,以字符串常量形式定义了各种事件类型并定义了一系列生命周期管理的方法和监听器的管理方法。

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

Tomcat通过Lifecycle接口将整个Tomcat各个组件串在一起,从而完成对各个组件统一的管理。这样我们只需要操作根组件就行了,Tomcat会递归地由父组件操作子组件,最终整个Tomcat就跑起来了。

  • LifecycleState类

作为事件源接口,以字符串常量形式定义了各种事件类型并定义了一系列生命周期管理的方法和监听器的管理方法。这个常量要么不设值,如果设置值则必须为Lifecycle接口中的常量值。

这里写图片描述

以下是这些生命周期状态之间的转化关系

这里写图片描述

  • LifecycleListener接口

LifecycleListener接口作为监听器接口,仅仅定义了一个方法用来在事件产生时通知相关的观察者。

这里写图片描述

  • LifecycleEvent类

LifecycleEvent类作为事件类,其继承自EventObject类,通过该类可以产生基于指定事件源(Lifecycle)的事件并可在需要的时候获取该事件源对象。当某个实现了Lifecycle接口的组件有变化时产生相应的事件并告知其观察者

这里写图片描述

此类继承自JDK里面的EventObject,那么这两个类是怎样关联起来的呢?

可以看到LifecycleEvent类的构造器中调用了超类的构造器,其超类构造器定义如下:

这里写图片描述

EventObject类中保存有事件源对象的引用,而调用getLifecycle时其实是调用了EventObject类的getSource方法,其实现如下:

这里写图片描述

  • LifecycleSupport类

LifecycleSupport类作为一个辅助类,封装了事件源(Lifecycle)和监听器(LifecycleListener),原本事件发生时应当由事件源调用自身的方法通知观察者,使用LifecycleSupport后,事件发生时由LifecycleSupport对象代为完成。其使用一个数组保存抽象观察者,并且和Lifycycle中管理观察者的方法具有相同的方法签名,这样可以起代理者的角色。
LifecycleSupport 类代理了所有主题对观察者的管理,将这个管理抽出来统一实现,以后如果修改只要修改 LifecycleSupport 类就可以了,不需要去修改主题,因为所有主题的对观察者的操作都被代理给 LifecycleSupport 类了。

这里写图片描述

LifecycleSupport类中用数组类型的变量listeners存储了所有监听器。

这里写图片描述

这里写图片描述

这里写图片描述

而通告观察者时其实是时遍历内部的观察者数组并调用它们的相关方法

这里写图片描述

  • 生命周期管理组件的父类LifecycleBase类

本类是所有需要进行生命周期管理的组件的父类,其实现了Lifecycle接口中的所有功能,解决了三个问题:

  1. 具体主题对其观察者的管理

    使用代理策略,其中代理模式的使用如下:

这里写图片描述

2.具体主题对其生命周期的管理
即事件源如何管理其生命周期。具体主题或各个实现了Lifecycle接口的组件必须自己实现管理自己生命周期的方法。为了达到这一目的,采用了回调模式。
这里写图片描述

这里写图片描述

这里写图片描述

回调模式贯穿于整个Tomcat,Lifecycle接口中start、stop、init、destory方法都使用了回调模式,。
LifecycleBase中关于生命周期管理的方法都是final方法,避免子类再去实现这些方法,但也提供了扩展,扩展方法在本类中采用abstract的形式,分别为startInternal、initInternal、stopInternal和destroyInternal,这些方法放到子类实现

3.事件源向监听器发布事件

即凡实现抽象主题接口的所有具体组件,如何向组件中已注册的监听器发布一个事件。这个发布事件的职责还是由LifecycleSupport完成,调用该类的addLifecycleListener方法增加监听器,需要发布事件时还是调用该工具类的fireLifecycleEvent方法,将事件发布给组件上注册的所有监听器,由监听器内部实现来决定是否处理该事件。而调用该工具类的fireLifecycleEvent方法是由LifecycleBase来代理的,代码如下:
这里写图片描述

这里写图片描述

这里写图片描述

从LifecycleSupport的fireLifecycleEvent方法代码可见,通过传进来的两个参数构造一个LifecycleEvent对象,然后向注册到组件中的所有监听器发布这个新构造的事件对象。

  • 具体的观察者—LifecycleListener的实现类

这里写图片描述

生命周期事件管理的过程

1注册事件监听器
在Catalina的load方法运行时会调用其createStartDigester方法,其实现如下:

这里写图片描述

这部分首先会生成LifecycleListener子类的实例。然后调用该实例的set方法为创建的实例添加属性,最后调用addLifecycleListener方法,根据sever.xml文件下listener节点所定义的className属性构造对象实例,并作为addLifecycleListener方法的参数。

这里写图片描述

从上面server.xml文件可见,Server节点下的Listener节点有好几个,这里以org.apache.catalina.mbeans.GlobalResourcesLifecycleListener举例。在构造完GlobalResourcesLifecycleListener类的对象之后,调用StandardServer的addLifecycleListener方法,这个方法并没有直接在StandardServer类中定义,而是在它的父类catalina.util.LifecycleBase中:

这里写图片描述

LifecycleBase其实是代理使用了LifecycleSupport类的addLifecycleListener方法

这里写图片描述

所以添加时实际上是把该监听器实例添加到这个list中,然后在事件发生时会遍历这个list,依次调用该list中所有的事件监听器的lifecycleEvent方法。

2 向事件监听器发布事件

以上步骤完成了监听器的注册,只有事件发生时,才发布事件(将事件发布给组件上注册的所有监听器),由监听器内部实现来决定是否处理该事件, tomcat中关于生命周期事件的发布是在组件初始化阶段需要完成的,我们仍然看看StandardServer的源码中start方法,在发现startInternal方法里面有一个setStateInternal方法,调用了父类LifecycleBase中的setState方法,最后调用LifecycleBase类的一个同步方法setStateInternal。

这里写图片描述

这里写图片描述

这里写图片描述

最后设置了当前的生命周期状态。

3 事件监听器的处理事件

总的来说注册事件和发布事件就是通过一个工具类LifecycleSupport,调用该类的addLifecycleListener方法增加监听器,需要发布事件时还是调用该类的fireLifecycleEvent方法,将事件发布给组件上注册的所有监听器,由监听器内部实现来决定是否处理该事件。这里以监听器GlobalResourcesLifecycleListener举例来说明事件监听器对事件的处理。

这里写图片描述

可以看到这个监听器只对start和stop事件感兴趣,只有相应的事件发生时才对进行处理。

原创粉丝点击