|
|
|
|
公众号矩阵

既然启动流程不太了解,那你知道Tomcat的生命周期是什么样子的么?

Tomcat的生命周期管理的话,我们不能总是从书中获取那些知识,而是结合实践,然后综合书中的内容,进行一层一层的深入分析,这样对自己记忆和理解都能更加的透彻。

作者: 鸭血粉丝 来源:Java极客技术 |2021-01-13 07:34

本文转载自微信公众号「Java极客技术」,作者鸭血粉丝 。转载本文请联系Java极客技术公众号。 

序言

Tomcat的生命周期管理的话,我们不能总是从书中获取那些知识,而是结合实践,然后综合书中的内容,进行一层一层的深入分析,这样对自己记忆和理解都能更加的透彻。

启动的时候的

大家可以随便找一个zip版本的Tomcat,然后直接启动起来,我们来看看是个什么样子的,

  1. 一月 11, 2021 10:16:24 上午 org.apache.coyote.AbstractProtocol init 
  2. 信息: Initializing ProtocolHandler ["http-bio-8080"
  3. 一月 11, 2021 10:16:24 上午 org.apache.coyote.AbstractProtocol init 
  4. 信息: Initializing ProtocolHandler ["ajp-bio-8009"
  5. 一月 11, 2021 10:16:24 上午 org.apache.catalina.startup.Catalina load 
  6. 信息: Initialization processed in 470 ms 
  7. 一月 11, 2021 10:16:24 上午 org.apache.catalina.core.StandardService startInternal 
  8. 信息: Starting service Catalina 
  9. 一月 11, 2021 10:16:24 上午 org.apache.catalina.core.StandardEngine startInternal 
  10. 信息: Starting Servlet Engine: Apache Tomcat/7.0.88 
  11. 一月 11, 2021 10:16:24 上午 org.apache.catalina.startup.HostConfig deployDirectory 

大家看到这个启动过程之后,在联想一下之前的文章中的Tomcat的启动流程,是不是又感觉有点那个味道了,load,然后start,最后然后stop了。

划重点1:Lifecycle

在之前的文章中,我们提到了Lifecycle, 而Tomcat也就是通过Lifecycle接口统一管理生命周期,所有有生命周期的组件都要实现Lifecycle接口,以便提供一致的机制去启动和停止组件。

那么我们就来分析一下这个Lifecycle接口里面都包含了哪些内容,大家可以直接去tomcat的包中的catalina的jar下面去寻找看一下,

  • 定义了13个String类型的变量
  • 定义了3个管理监听器的方法
  • 定义了4个生命周期
  • 定义了2个获取当前状态的方法

那么我们先说这个13个变量:

  1. String BEFORE_INIT_EVENT = "before_init"
  2.    String AFTER_INIT_EVENT = "after_init"
  3.    String START_EVENT = "start"
  4.    String BEFORE_START_EVENT = "before_start"
  5.    String AFTER_START_EVENT = "after_start"
  6.    String STOP_EVENT = "stop"
  7.    String BEFORE_STOP_EVENT = "before_stop"
  8.    String AFTER_STOP_EVENT = "after_stop"
  9.    String AFTER_DESTROY_EVENT = "after_destroy"
  10.    String BEFORE_DESTROY_EVENT = "before_destroy"
  11.    String PERIODIC_EVENT = "periodic"
  12.    String CONFIGURE_START_EVENT = "configure_start"
  13.    String CONFIGURE_STOP_EVENT = "configure_stop"

这13个变量是什么意思呢?在《Tomcat架构解析》一书中说到,这些常量信息用于LifecycleEvent事件的type属性中,作用是区分组件发出的LifecycleEvent事件时的状态(如初始化前、启动前、启动中等)。这种设计方法可以让多种状态都发送同一种类型的时间,然后用其中的一个属性类区分状态而不用定义多种事件。

其实大家可以根据变量的名字就能看出来,初始化前,初始化后,启动,启动前,启动后。。。。说的在直白一点 ,就是为了表示组件发出时的状态而已。

而三个管理监听的方法又是什么呢?

  1. void addLifecycleListener(LifecycleListener var1); 
  2.  
  3. LifecycleListener[] findLifecycleListeners(); 
  4.  
  5. void removeLifecycleListener(LifecycleListener var1); 

而这个三个监听器也分别就是用来添加,查找和删除LifecycleListener类型的监听器。这里面是三个接口,具体实现一会我们去子类里面找,在这里先知道有这么个东西就行,下面就会直接分析。

4个生命周期

这个就肯定很简单了,比如像我们都知道在Servlet的生命周期一样,init,start,stop,destroy,初始化,启动,停止,销毁,

  1. void init() throws LifecycleException; 
  2.  
  3. void start() throws LifecycleException; 
  4.  
  5. void stop() throws LifecycleException; 
  6.  
  7. void destroy() throws LifecycleException; 

2个获取状态的方法

  1. LifecycleState getState(); 
  2.  
  3. String getStateName(); 

毕竟这个Lifecycle是一个接口,它并不是具体的实现类,我们想要了解这个,那么就一定得去具体的实现类里面去找寻这个内容,那么他的实现类是什么呢?来了来了,它来了,LifecycleBase

LifecycleBase

LifecycleBase是抽象类,是tomcat中所有组件类的基类,他实现了Lifecycle,但是Tomcat下的很多子类也同样的继承了它,所以他也是非常重要的,

  1. public abstract class LifecycleBase implements Lifecycle { 
  2.  private LifecycleSupport lifecycle = new LifecycleSupport(this); 
  3.  // 源组件的当前状态,不同状态触发不同事件 
  4.     private volatile LifecycleState state; 
  5.     public LifecycleBase() { 
  6.         this.state = LifecycleState.NEW; 
  7.     } 
  8.    } 

在这里我们还要注意一下这个LifecycleSupport类,LifecycleSupport中定义了一个LifecycleListener数组类型的属性来保存所有的监听器,然后在里面分别定义了添加,删除,查找,执行监听器的方法,不信的话,我们来看看,毕竟这个类放在这里先new出来也是有一定道理的。

  1. public final class LifecycleSupport { 
  2.     private Lifecycle lifecycle = null
  3.     private LifecycleListener[] listeners = new LifecycleListener[0]; 
  4.     private final Object listenersLock = new Object(); 
  5.  
  6.     public LifecycleSupport(Lifecycle lifecycle) { 
  7.         this.lifecycle = lifecycle; 
  8.     } 
  9.  
  10.     public void addLifecycleListener(LifecycleListener listener) { 
  11.         Object var2 = this.listenersLock; 
  12.         synchronized(this.listenersLock) { 
  13.             LifecycleListener[] results = new LifecycleListener[this.listeners.length + 1]; 
  14.  
  15.             for(int i = 0; i < this.listeners.length; ++i) { 
  16.                 results[i] = this.listeners[i]; 
  17.             } 
  18.  
  19.             results[this.listeners.length] = listener; 
  20.             this.listeners = results; 
  21.         } 
  22.     } 
  23.  
  24.     public LifecycleListener[] findLifecycleListeners() { 
  25.         return this.listeners; 
  26.     } 
  27.  
  28.     public void fireLifecycleEvent(String type, Object data) { 
  29.         LifecycleEvent event = new LifecycleEvent(this.lifecycle, type, data); 
  30.         LifecycleListener[] interested = this.listeners; 
  31.  
  32.         for(int i = 0; i < interested.length; ++i) { 
  33.             interested[i].lifecycleEvent(event); 
  34.         } 
  35.  
  36.     } 
  37.  
  38.     public void removeLifecycleListener(LifecycleListener listener) { 
  39.         Object var2 = this.listenersLock; 
  40.         synchronized(this.listenersLock) { 
  41.             int n = -1; 
  42.  
  43.             for(int i = 0; i < this.listeners.length; ++i) { 
  44.                 if (this.listeners[i] == listener) { 
  45.                     n = i; 
  46.                     break; 
  47.                 } 
  48.             } 
  49.  
  50.             if (n >= 0) { 
  51.                 LifecycleListener[] results = new LifecycleListener[this.listeners.length - 1]; 
  52.                 int j = 0; 
  53.  
  54.                 for(int i = 0; i < this.listeners.length; ++i) { 
  55.                     if (i != n) { 
  56.                         results[j++] = this.listeners[i]; 
  57.                     } 
  58.                 } 
  59.  
  60.                 this.listeners = results; 
  61.             } 
  62.         } 
  63.     } 

话不多说,我们继续往下,它的生命周期方法又是什么呢?这才是今天的重点。之前我们就说生命周期包含了哪些内容,从init开始,然后start,然后stop以及最后的destroy方法,在实现类里面表现的那是淋漓尽致。

init方法

  1. public final synchronized void init() throws LifecycleException { 
  2.        //这里表示只有NEW状态下是可以使用的, 
  3.        if (!this.state.equals(LifecycleState.NEW)) { 
  4.            this.invalidTransition("before_init"); 
  5.        } 
  6.    //在这里通过不同的状态,然后去触发不同的事件, 
  7.        try { 
  8.            //设置生命周期状态为INITIALIZING 
  9.            this.setStateInternal(LifecycleState.INITIALIZING, (Object)nullfalse); 
  10.            //执行方法 
  11.            this.initInternal(); 
  12.            //设置生命周期状态为INITIALIZED 
  13.            this.setStateInternal(LifecycleState.INITIALIZED, (Object)nullfalse); 
  14.        } catch (Throwable var2) { 
  15.            ExceptionUtils.handleThrowable(var2); 
  16.            this.setStateInternal(LifecycleState.FAILED, (Object)nullfalse); 
  17.            throw new LifecycleException(sm.getString("lifecycleBase.initFail", new Object[]{this.toString()}), var2); 
  18.        } 
  19.    } 

start方法

  1. public final synchronized void start() throws LifecycleException { 
  2.    //在这里验证生命周期状态,状态是这三种状态的是为不可用状态STARTING_PREP,STARTING,STARTED 
  3.        if (!LifecycleState.STARTING_PREP.equals(this.state) && !LifecycleState.STARTING.equals(this.state) && !LifecycleState.STARTED.equals(this.state)) { 
  4.            //如果是NEW状态,执行init方法 
  5.            if (this.state.equals(LifecycleState.NEW)) { 
  6.                this.init(); 
  7.            //如果是FAILED状态,那么执行stop方法 
  8.            } else if (this.state.equals(LifecycleState.FAILED)) { 
  9.                this.stop(); 
  10.            //如果是INITIALIZED状态,那么就会告诉你是个非法的操作 
  11.            } else if (!this.state.equals(LifecycleState.INITIALIZED) && !this.state.equals(LifecycleState.STOPPED)) { 
  12.                this.invalidTransition("before_start"); 
  13.            } 
  14.  
  15.            try { 
  16.                //设置启动状态为 STARTING_PREP 
  17.                this.setStateInternal(LifecycleState.STARTING_PREP, (Object)nullfalse); 
  18.                this.startInternal(); 
  19.                //这里就非常的严谨,他会在启动之后,继续去看状态是什么,保证启动成功 
  20.                if (this.state.equals(LifecycleState.FAILED)) { 
  21.                    this.stop(); 
  22.                } else if (!this.state.equals(LifecycleState.STARTING)) { 
  23.                    this.invalidTransition("after_start"); 
  24.                } else { 
  25.                    this.setStateInternal(LifecycleState.STARTED, (Object)nullfalse); 
  26.                } 
  27.  
  28.            } catch (Throwable var2) { 
  29.                ExceptionUtils.handleThrowable(var2); 
  30.                this.setStateInternal(LifecycleState.FAILED, (Object)nullfalse); 
  31.                throw new LifecycleException(sm.getString("lifecycleBase.startFail", new Object[]{this.toString()}), var2); 
  32.            } 
  33.        } else { 
  34.            if (log.isDebugEnabled()) { 
  35.                Exception e = new LifecycleException(); 
  36.                log.debug(sm.getString("lifecycleBase.alreadyStarted", new Object[]{this.toString()}), e); 
  37.            } else if (log.isInfoEnabled()) { 
  38.                log.info(sm.getString("lifecycleBase.alreadyStarted", new Object[]{this.toString()})); 
  39.            } 
  40.  
  41.        } 
  42.    } 

stop方法

  1. public final synchronized void stop() throws LifecycleException { 
  2.        //同样的,和上面一样,三种状态下不可执行 
  3.        if (!LifecycleState.STOPPING_PREP.equals(this.state) && !LifecycleState.STOPPING.equals(this.state) && !LifecycleState.STOPPED.equals(this.state)) { 
  4.            //如果是NEW状态,状态直接修改为STOPPED 
  5.            if (this.state.equals(LifecycleState.NEW)) { 
  6.                this.state = LifecycleState.STOPPED; 
  7.            } else { 
  8.                //如果不是这2中状态,那么就直接异常 
  9.                if (!this.state.equals(LifecycleState.STARTED) && !this.state.equals(LifecycleState.FAILED)) { 
  10.                    this.invalidTransition("before_stop"); 
  11.                } 
  12.                try { 
  13.                    if (this.state.equals(LifecycleState.FAILED)) { 
  14.                        this.fireLifecycleEvent("before_stop", (Object)null); 
  15.                    } else { 
  16.                        this.setStateInternal(LifecycleState.STOPPING_PREP, (Object)nullfalse); 
  17.                    } 
  18.                    this.stopInternal(); 
  19.                    if (!this.state.equals(LifecycleState.STOPPING) && !this.state.equals(LifecycleState.FAILED)) { 
  20.                        this.invalidTransition("after_stop"); 
  21.                    } 
  22.                    this.setStateInternal(LifecycleState.STOPPED, (Object)nullfalse); 
  23.                } catch (Throwable var5) { 
  24.                    ... 
  25.                } finally { 
  26.                   ... 
  27.                } 
  28.  
  29.            } 
  30.        } else { 
  31.            ... 
  32.        } 
  33.    } 

destroy方法

  1. public final synchronized void destroy() throws LifecycleException { 
  2.         //如果状态是启动失败的,也就是FAILED,那么会直接去调用stop方法, 
  3.         if (LifecycleState.FAILED.equals(this.state)) { 
  4.             try { 
  5.                 this.stop(); 
  6.             } catch (LifecycleException var3) { 
  7.                 log.warn(sm.getString("lifecycleBase.destroyStopFail", new Object[]{this.toString()}), var3); 
  8.             } 
  9.         } 
  10.         //如果是这两种状态DESTROYING、DESTROYED,那么就不再进行执行了,直接进行return 
  11.         if (!LifecycleState.DESTROYING.equals(this.state) && !LifecycleState.DESTROYED.equals(this.state)) { 
  12.             if (!this.state.equals(LifecycleState.STOPPED) && !this.state.equals(LifecycleState.FAILED) && !this.state.equals(LifecycleState.NEW) && !this.state.equals(LifecycleState.INITIALIZED)) { 
  13.                 this.invalidTransition("before_destroy"); 
  14.             } 
  15.  
  16.             try { 
  17.                 this.setStateInternal(LifecycleState.DESTROYING, (Object)nullfalse); 
  18.                 this.destroyInternal(); 
  19.                 this.setStateInternal(LifecycleState.DESTROYED, (Object)nullfalse); 
  20.             } catch (Throwable var2) { 
  21.                 ExceptionUtils.handleThrowable(var2); 
  22.                 this.setStateInternal(LifecycleState.FAILED, (Object)nullfalse); 
  23.                 throw new LifecycleException(sm.getString("lifecycleBase.destroyFail", new Object[]{this.toString()}), var2); 
  24.             } 
  25.         } else { 
  26.          ... 
  27.         } 
  28.     } 

阿粉在其中精简了一些代码,如果大家有兴趣的可以自己去翻一下源码,然后自己去看一下,这样对比出来才有效果。

总结

其实就是通过不同的状态转变,然后相应的去调用init、start、stop、destroy方法,然后提供所有Tomcat组件的生命周期管理。

上图就是接口状态不同情况执行不同方法的图,图片来自《Tomcat架构解析》

文献参考

《深入剖析Tomcat》 《Tomcat架构解析》 《Servlet/JSP深入详解》

【编辑推荐】

  1. 聊一聊如何SpringBoot外置Tomcat
  2. 程序员效率工具:画流程图常用的工具
  3. 谁说明天上线,这货压根不知道开发流程!
  4. 行业观点:人工智能如何革新业务流程
  5. 面试官:来说说Tomcat的启动过程是什么样子的
【责任编辑:武晓燕 TEL:(010)68476606】

点赞 0
分享:
大家都在看
猜你喜欢

订阅专栏+更多

数据湖与数据仓库的分析实践攻略

数据湖与数据仓库的分析实践攻略

助力现代化数据管理:数据湖与数据仓库的分析实践攻略
共3章 | 创世达人

1人订阅学习

云原生架构实践

云原生架构实践

新技术引领移动互联网进入急速赛道
共3章 | KaliArch

30人订阅学习

数据中心和VPDN网络建设案例

数据中心和VPDN网络建设案例

漫画+案例
共20章 | 捷哥CCIE

209人订阅学习

视频课程+更多

订阅51CTO邮刊

点击这里查看样刊

订阅51CTO邮刊

51CTO服务号

51CTO官微