Jetty - LifeCycle源码分析
1. 描述
基于Jetty-9.4.8.v20171121。
LifeCycle主要管理Jetty里面通用组件的生命周期,比如组件启动中、启动、运行、停止中、停止等,实现该接口就可以定义一套生命周期。
其中通用组件比如Server,Connector,Handler等,Jetty把很多对象当成组件来管理并且都是LifeCycle的子类。
1.1 API
LifeCycle与其内部类LifeCycle.Listener是一个典型的观察者设计模式,LifeCycle是被观察者,LifeCycle.Listener是观察者。
其中也透漏一种编码范式:观察者模式的编码范式,Jetty里面Container组件与其内部类Container.Listener也是观察者设计模式也遵循这样的编码范式。
- @ManagedObject("Lifecycle Interface for startable components")
- public interface LifeCycle
- {
- // 启动组件
- @ManagedOperation(value="Starts the instance", impact="ACTION")
- public void start()
- throws Exception;
- // 停止组件,组件可以等待当前的活动正常完成,但是它可以被中断。
- @ManagedOperation(value="Stops the instance", impact="ACTION")
- public void stop()
- throws Exception;
- // 如果组件在启动中或已经启动
- public boolean isRunning();
- // 如果组件已经启动
- public boolean isStarted();
- // 如果组件启动中
- public boolean isStarting();
- // 如果组件停止中
- public boolean isStopping();
- // 如果组件已经停止
- public boolean isStopped();
- // 如果组件启动失败或停止失败
- public boolean isFailed();
- /* ------------------------------------------------------------ */
- public void addLifeCycleListener(LifeCycle.Listener listener);
- /* ------------------------------------------------------------ */
- public void removeLifeCycleListener(LifeCycle.Listener listener);
- // 监听器,监听Lifecycle事件
- public interface Listener extends EventListener
- {
- public void lifeCycleStarting(LifeCycle event);
- public void lifeCycleStarted(LifeCycle event);
- public void lifeCycleFailure(LifeCycle event,Throwable cause);
- public void lifeCycleStopping(LifeCycle event);
- public void lifeCycleStopped(LifeCycle event);
- }
- // 如果object实例是一个Lifecycle对象,则启动。如果异常统一转换为RuntimeException
- public static void start(Object object)
- {
- if (object instanceof LifeCycle)
- {
- try
- {
- ((LifeCycle)object).start();
- }
- catch(Exception e)
- {
- throw new RuntimeException(e);
- }
- }
- }
- // 如果object实例是一个Lifecycle对象,则停止。如果异常统一转换为RuntimeException
- public static void stop(Object object)
- {
- if (object instanceof LifeCycle)
- {
- try
- {
- ((LifeCycle)object).stop();
- }
- catch(Exception e)
- {
- throw new RuntimeException(e);
- }
- }
- }
- }
1.2 类图
LifeCycle是Jetty主要类的基本特征。
将这些接口,抽象类,类分为3层方便理解:
(1)组件接口层:主要包括LifeCycle,Connector,Handler,Container这些组件的高层接口定义;
(2)组件实现层:主要包括各个组件的默认实现;
(3)组件应用层:主要涉及具体的应用,如:ServerConnector负责HTTP等协议的连接,Server是Jetty中唯一的服务。
类图如下:
Jetty重要的组件Server,Handler,Connector和Container都是LifeCycle子类。
沿着组件的继承关系,可以看出都有一个默认实现AbstractXXX类,这些默认实现已经帮我们完成了大部分功能,差异性都放在子类中实现。
由于我们主要关心LifeCycle,所以我们重点源码分析AbstractLifeCycle的实现。
2. AbstractLifeCycle抽象类
从上面LifeCycle的API可以看出,具有生命周期的类主要具有的能力是:启动、停止和注册LifeCycle状态变化的监听器,主要有5种状态需要监听:启动中,启动,失败,停止中,停止。其中,失败包括启动失败和停止失败。
2.1 API
- // 组件生命周期的基本实现
- @ManagedObject("Abstract Implementation of LifeCycle")
- public abstract class AbstractLifeCycle implements LifeCycle
- // 6种状态定义
- public static final String STOPPED="STOPPED";
- public static final String FAILED="FAILED";
- public static final String STARTING="STARTING";
- public static final String STARTED="STARTED";
- public static final String STOPPING="STOPPING";
- public static final String RUNNING="RUNNING";
- // 保存关心该组件声明周期变化的监听器;
- // 这个是典型观察者模式(AbstractLifeCycle是被观察者,Listener是观察者)
- private final CopyOnWriteArrayList<LifeCycle.Listener> _listeners=new CopyOnWriteArrayList<LifeCycle.Listener>();
- // 锁对象,与组件实例绑定,用于组件的启停等同步操作
- private final Object _lock = new Object();
- private final int __FAILED = -1, __STOPPED = 0, __STARTING = 1, __STARTED = 2, __STOPPING = 3;
- private volatile int _state = __STOPPED;
- private long _stopTimeout = 30000;
- // AbstractLifeCycle对象提供的两个方法,这两个方法默认是个空实现
- // 实际上,继承AbstractLifeCycle可能是具体的组件,只有这个具体的组件才清楚自己的真实启停过程;所以需要子类自己实现
- protected void doStart() {}
- protected void doStop() {}
- // AbstractLifeCycle实际提供的是一个模板式的启停步骤,具体的步骤是放在子类的doStart和doStop中实现的,也就是上面定义的两个方法
- // 此处是个典型的模板方法设计模式:模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关系。
// 通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中,在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。
// 模板方法模式提供了一个模板方法来定义算法框架,而某些具体步骤的实现可以在其子类中完成。- // 自己的感悟:设计模式贵在积累,不存在一步就位,各种源代码是最直接的学习资料,第一步就是要善于在源码中正确的识别各种设计模式。
- @Override
- public final void start() throws Exception
- {
- synchronized (_lock)
- {
- try
- {
- if (_state == __STARTED || _state == __STARTING)
- return;
- setStarting();
- doStart();
- setStarted();
- }
- catch (Throwable e)
- {
- setFailed(e);
- throw e;
- }
- }
- }
- @Override
- public final void stop() throws Exception
- {
- synchronized (_lock)
- {
- try
- {
- if (_state == __STOPPING || _state == __STOPPED)
- return;
- setStopping();
- doStop();
- setStopped();
- }
- catch (Throwable e)
- {
- setFailed(e);
- throw e;
- }
- }
- }
- // 单独提这个方法:这个方法在判断是否运行,为啥需要用一个变量先引用_state,而不是直接判断,主要是为了并发的问题,Jetty里有很多这样的用法。
- @Override
- public boolean isRunning()
- {
- final int state = _state;
- return state == __STARTED || state == __STARTING;
- }
- @Override
- public void addLifeCycleListener(LifeCycle.Listener listener)
- {
- _listeners.add(listener);
- }
- @Override
- public void removeLifeCycleListener(LifeCycle.Listener listener)
- {
- _listeners.remove(listener);
- }
- // 如下是设置组件状态,并且通知相关的监听器
- private void setStarted()
- {
- _state = __STARTED;
- if (LOG.isDebugEnabled())
- LOG.debug(STARTED+" @{}ms {}",Uptime.getUptime(),this);
- for (Listener listener : _listeners)
- listener.lifeCycleStarted(this);
- }
- private void setStarting()
- {
- if (LOG.isDebugEnabled())
- LOG.debug("starting {}",this);
- _state = __STARTING;
- for (Listener listener : _listeners)
- listener.lifeCycleStarting(this);
- }
- private void setStopping()
- {
- if (LOG.isDebugEnabled())
- LOG.debug("stopping {}",this);
- _state = __STOPPING;
- for (Listener listener : _listeners)
- listener.lifeCycleStopping(this);
- }
- private void setStopped()
- {
- _state = __STOPPED;
- if (LOG.isDebugEnabled())
- LOG.debug("{} {}",STOPPED,this);
- for (Listener listener : _listeners)
- listener.lifeCycleStopped(this);
- }
- private void setFailed(Throwable th)
- {
- _state = __FAILED;
- if (LOG.isDebugEnabled())
- LOG.warn(FAILED+" " + this+": "+th,th);
- for (Listener listener : _listeners)
- listener.lifeCycleFailure(this,th);
- }
- }
从LifeCycle接口的API和AbstractLifeCycle抽象类的实现来看,AbstractLifeCycle已经基本实现了LifeCycle的全部功能。
Jetty - LifeCycle源码分析的更多相关文章
- Jetty - Container源码分析
1. 描述 Container提供管理bean的能力. 基于Jetty-9.4.8.v20171121. 1.1 API public interface Container { // 增加一个bea ...
- Jetty - Connector源码分析
1. 描述 基于Jetty-9.4.8.v20171121. Connector接受远程机器的连接和数据,允许应用向远程机器发送数据. 1.2 类图 从类图看出AbstractConnector继承C ...
- Jetty 9 源码分析 Connector及Server类(一)
本文的源码基于Jetty9,主要分析了Jetty 的Connector与Server类间在Jetty启动过程中的一些细节.Jetty9 对以前的Connector体系进行了重构, 结构与6和7都不同, ...
- Jetty - Handler源码分析
1. 描述 基于Jetty-9.4.8.v20171121. Handler是Jetty服务处理器,用户Server处理HTTP请求. Handler可以做如下处理: (1)完全生成HTTP响应: ( ...
- jetty加载spring-context容器源码分析
带着疑问开始 web.xml的顺序问题 先拿一个最简单的spring mvc web.xml来说问题,如下图:如果我将三者的顺序倒置或是乱置,会产生什么结果呢? 启动报错?还是加载未知结果?还是毫无影 ...
- spark源码分析以及优化
第一章.spark源码分析之RDD四种依赖关系 一.RDD四种依赖关系 RDD四种依赖关系,分别是 ShuffleDependency.PrunDependency.RangeDependency和O ...
- tomcat源码--springboot整合tomcat源码分析
1.测试代码,一个简单的springboot web项目:地址:https://gitee.com/yangxioahui/demo_mybatis.git 一:tomcat的主要架构:1.如果我们下 ...
- 精尽Spring Boot源码分析 - 内嵌Tomcat容器的实现
该系列文章是笔者在学习 Spring Boot 过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring Boot 源码分析 GitHub 地址 进行阅读 Sprin ...
- Tomcat源码分析
前言: 本文是我阅读了TOMCAT源码后的一些心得. 主要是讲解TOMCAT的系统框架, 以及启动流程.若有错漏之处,敬请批评指教! 建议: 毕竟TOMCAT的框架还是比较复杂的, 单是从文字上理解, ...
随机推荐
- 【java】随机生成6位的数字 /生成例如010 045这样的三位数
int radomInt = new Random().nextInt(999999) @org.junit.Test public void testName() throws Exception ...
- Laravel技⃣术⃣特⃣点⃣
1.Bundle是Laravel的扩展包组织形式或称呼.Laravel的扩展包仓库已经相当成熟了,可以很容易的帮你把扩展包(bundle)安装到你的应用中.你可以选择下载一个扩展包(bundle)然后 ...
- Unity3d通用工具类之定时触发器
时隔多日,好不容易挤出点时间来写写博文.不容易,请送我几朵红花,点个赞也行. 今天呢,我们主要来扩展下通用工具类==>定时触发器. 顾名思义,所谓的定时触发器,就是告诉程序在过多长时间后,我要执 ...
- WebLogic 1036的镜像构建
WebLogic1035版本构建出来的镜像有问题,部署应用激活后返回的是后面pod的ip和端口号,在1036版本和12.1.3版本都无此问题. weblogic 1036的Dockerfile [ro ...
- mysql: Error Codes and Messages
Appendix B. Error Codes and MessagesTable of Contents B.1. Server Error Codes and MessagesB.2. Clien ...
- C语言void关键字的深刻含义
C语言void关键字的深刻含义 .概述 本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧. .void的含义 void的字面意思是“无类型”,void *则为 ...
- 各种软核处理器二进制文件FPGA初始化文件生成程序
不管是MIPS, Nios II, MicroBlaze, MSP430, 8051, OpenRISC, OpenSPARC, LEON2/LEON3等等软核处理器,在FPGA上实现的时候我们通常需 ...
- 可以ping通虚拟机但不能telnet 9000端口
突然发现eclipse不能连上虚拟机了,报错是本机连接不上9000的端口. 觉得有点奇怪,就在命令行里试图ping通虚拟机,成功:但尝试这telnet 9000端口的时候,却报错连接不上. 上网查了这 ...
- SqlBulkCopy-从 bcp 客户端收到一个对 colid 1 无效的列长度
经过研究,问题是因为tatatable中的colid列1的数据字段长度超过了数据表中定义的字段长度. 解决方法就是将数据库该字段的长度增大问题就解决了.
- java中的初始化块
public class Person { int a=6;//声明实例变量制定默认值,也可以认为是对象的初始化代码,执行顺序与源代码中的排列顺序相同 { System.out.println(&qu ...