【Tomcat】【二】Tomcat 的生命周期管理

1  前言

  这节我们来看下 Tomcat 中的生命周期哈,一样边看边记录一下,先通读一遍理解,理解完再记录加强一遍。

2  Lifecycle 接口

  Tomcat 通过 orgapachecatalina.Lifecycle 接口统一管理生命周期,所有有生命周期的组件都要实现 Lifecycle 接口。Lifecycle 接口一共做了4件事:

  • 定义了13 个String类型常量,用于 LifecycleEvent事件的 type 属性中,作用是区分组件发出的 LifecycleEvent 事件时的状态(如初始化前、启动前、启动中等)。这种设计方式可以让多种状态都发送同一种类型的事件(LifecycleEvent)然后用其中的一个属性来区分状态而不用定义多种事件,我们要学习和借鉴这种方式。
  • 定义了三个管理监听器的方法 addLifecycleListener、findLifecycleListeners 和remove-LifecycleListener,分别用来添加、查找和删除 LifecycleListener 类型的监听器。
  • 定义了4个生命周期的方法:init、start、stop 和destroy,用于执行生命周期的各个阶段的操作。

  • 定义了获取当前状态的两个方法 getState和getStateName,用来获取当前的状态getState 的返回值 LifecycleState是枚举类型,里边列举了生命周期的各个节点getStateName方法返回String类型的状态的名字,主要用于JMX中。

3  LifecycleBase

  Lifecycle 的默认实现是 orgapache.catalina.util.LifecycleBase,所有实现了生命周期的组件都直接或间接地继承自 LifecycleBase,LifecycleBase 为 Lifecycle 里的接口方法提供了默认实现:监听器管理是专门使用了一个 LifecycleSupport 类来完成的,LifecycleSupport 中定义了一个LifecycleListener 数组类型的属性来保存所有的监听器,然后并定义了添加、删除、查找和执行监听器的方法;生命周期方法中设置了相应的状态并调用了相应的模板方法,init、start、stop 和 destroy 所对应的模板方法分别是 initInternal、startInternal、stopInternal和destroyIntermal方法,这四个方法由子类具体实现,所以对于子类来说,执行生命周期处理的方法就是initInternal、startInternal、stopInternal和 destroyInternal;组件当前的状态在生命周期的四个方法中已经设置好了,所以这时直接返回去就可以了。下面分别来看一下实现的过程。

  LifecycleBase 中的addLifecycleListener、fndLifecycleListeners 和 removeLifecycleListener方法分别调用了 LifecycleSupport 中的同名方法,LifecycleSupport 监听器是通过一个数组属性listeners 来保存的,代码如下:

 

   这三个方法的实现非常简单,就是对 listeners 属性进行操作,只是因为 listeners 是数组类型,所以具体操作起来有点复杂,添加的时候先新建一个比当前数组大1的数组,然后将原来的数据按顺序保存进去,并将新的添加进去,最后将新建的数组赋给 listeners 属性,删除的时候要先找到要删除的监听器在数组中的序号,然后也是新建一个比当前数组小1的数组,接着将除了要删除的监听器所在序号的元素按顺序添加进去,最后再赋值给 listeners 属性。另外 LifecycleSupport 中还定义了处理 LifecycleEvent 事件的 fireLifecycleEvent方法,代码如下:

  

  这里按事件的类型(组件的状态)创建了 LifecycleEvent 事件,然后遍历所有的监听器进行了处理。

  四个生命周期方法
  四个生命周期方法的实现中首先判断当前的状态和要处理的方法是否匹配,如果不匹配就会执行相应方法使其匹配(如在 init 之前调用了 start,这时会先执行 nit 方法),或者不处理甚至抛出异常,如果匹配或者处理后匹配了,则会调用相应的模板方法并设置相应的状态。

  LifecycleBase 中的状态是通过 LifecycleState类型的state 属性来保存的,最开始初始化值为LifecycleState.NEW。我们来看一下init 方法:

  

  因为init 方法是最开始,所以状态必须是 LifecycleState.NEW,如果不是就抛出异常如果开始的状态是 LifecycleState.NEW,在具体初始化之前会将状态设置为 LifecycleState.INITIALIZING,然后调用模板方法 nitInternal让子类具体执行初始化,初始化完成后将状态设置为 LifecycleState.INTIALIZED。

   init方法中如果状态不是LifecycleStateNEW会调用invalidTransition 方法抛出异常invalidTransition 方法专门用于处理不符合要求的状态,在另外三个方法中如果状态也不合适而且不能进行别的处理,也会调用invalidTransition 方法,其代码如下:

  

 

   

   start 方法在启动前先判断是不是已经启动了,如果已经动了则直接返回,如果没有初始化会先执行初始化,如果是失败在状态就会调用 stop 方法进行关闭,如果状态不是前面那些也不是刚初始化完或者已经停止了则会抛出异常。如果状态是刚初始化完或者已经停止了则会先将状态设置为 LifecycleStateSTARTING PREP,然后执行startIntermal 模板方法调用子类的具体启动逻辑进行启动,最后根据是否启动成功设置相应的状态。其实主要就是各种状态的判断设置,stop和destroy 方法的实现过程也差不多,就不具体分析了。

  设置状态的 setStateInternal 方法中除了设置状态还可以检查设置的状态合不合逻辑,并且会在最后发布相应的事件,其代码如下:

  

   setStatelnternal方法中通过 check参数判断是否需要检查传入的状态,如果需要检查则会检查传入的状态是否为空和是否符合逻辑,最后将传入的状态设置到 state 属性,并调用 fireLifecycleEvent方 法处理事件,freLifecycleEvent法调用了LifecycleSupport 的fireLifecycleEvent 方法来具体处理,代码如下:

  

   LifecycleSupport 的 fireLifecycleEvent 方法前面已经介绍过了,它里面首先创建了 LifecycleEvent事件,然后遍历所有的监听器进行处理。 

  两个获取当前状态的方法
  在生命周期的相应方法中已经将状态设置到了 state 属性,所以获取状态的两个方法的实现就非常简单了,直接将 state 返回就可以了,代码如下:

  

4  小结

生命周期接口 Lifecycle,基础实现类 LifecycleBase,里边涉及到状态、事件、监听器以及生命周期的钩子,有理解不对的地方欢迎指正哈。

posted @ 2023-03-20 22:09  酷酷-  阅读(86)  评论(0编辑  收藏  举报