
生命周期管理LifeCycle我从以下几方面帮助你构建基于上下文的知识体系和理解为什么要理解组件的生命周期管理LifeCycle)Server及其它组件Server后续组件生命周期及初始化Server的依赖结构LifeCycle接口理解Lifecycle主要有两点第一是三类接口方法第二是状态机。一个标准的LifeCycle有哪些方法分三类去看javapublic interface Lifecycle { /** 第1类针对监听器 **/ // 添加监听器 public void addLifecycleListener(LifecycleListener listener); // 获取所以监听器 public LifecycleListener[] findLifecycleListeners(); // 移除某个监听器 public void removeLifecycleListener(LifecycleListener listener); /** 第2类针对控制流程 **/ // 初始化方法 public void init() throws LifecycleException; // 启动方法 public void start() throws LifecycleException; // 停止方法和start对应 public void stop() throws LifecycleException; // 销毁方法和init对应 public void destroy() throws LifecycleException; /** 第3类针对状态 **/ // 获取生命周期状态 public LifecycleState getState(); // 获取字符串类型的生命周期状态 public String getStateName(); }LifeCycle状态机有哪些状态Tomcat 给各个组件定义了一些生命周期中的状态在枚举类 LifecycleState 里javapublic enum LifecycleState { NEW(false, null), INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT), INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT), STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT), STARTING(true, Lifecycle.START_EVENT), STARTED(true, Lifecycle.AFTER_START_EVENT), STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT), STOPPING(false, Lifecycle.STOP_EVENT), STOPPED(false, Lifecycle.AFTER_STOP_EVENT), DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT), DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT), FAILED(false, null); private final boolean available; private final String lifecycleEvent; private LifecycleState(boolean available, String lifecycleEvent) { this.available available; this.lifecycleEvent lifecycleEvent; } …… }它们之间的关系是怎么样的呢在Lifecycle.java源码中有相关的注释看不太清楚的可以看下图LifecycleBase - LifeCycle的基本实现LifecycleBase是Lifecycle的基本实现。监听器相关生命周期监听器保存在一个线程安全的CopyOnWriteArrayList中。所以add和remove都是直接调用此List的相应方法。 findLifecycleListeners返回的是一个数组为了线程安全所以这儿会生成一个新数组。javaprivate final ListLifecycleListener lifecycleListeners new CopyOnWriteArrayList(); Override public void addLifecycleListener(LifecycleListener listener) { lifecycleListeners.add(listener); } Override public LifecycleListener[] findLifecycleListeners() { return lifecycleListeners.toArray(new LifecycleListener[0]); } Override public void removeLifecycleListener(LifecycleListener listener) { lifecycleListeners.remove(listener); }生命周期相关initjavaOverride public final synchronized void init() throws LifecycleException { // 非NEW状态不允许调用init()方法 if (!state.equals(LifecycleState.NEW)) { invalidTransition(Lifecycle.BEFORE_INIT_EVENT); } try { // 初始化逻辑之前先将状态变更为INITIALIZING setStateInternal(LifecycleState.INITIALIZING, null, false); // 初始化该方法为一个abstract方法需要组件自行实现 initInternal(); // 初始化完成之后状态变更为INITIALIZED setStateInternal(LifecycleState.INITIALIZED, null, false); } catch (Throwable t) { // 初始化的过程中可能会有异常抛出这时需要捕获异常并将状态变更为FAILED ExceptionUtils.handleThrowable(t); setStateInternal(LifecycleState.FAILED, null, false); throw new LifecycleException( sm.getString(lifecycleBase.initFail,toString()), t); } }我们再来看看invalidTransition方法该方法直接抛出异常。javaprivate void invalidTransition(String type) throws LifecycleException { String msg sm.getString(lifecycleBase.invalidTransition, type, toString(), state); throw new LifecycleException(msg); }setStateInternal方法用于维护状态同时在状态转换成功之后触发事件。为了状态的可见性所以state声明为volatile类型的。javaprivate volatile LifecycleState state LifecycleState.NEW;。 private synchronized void setStateInternal(LifecycleState state, Object data, boolean check) throws LifecycleException { if (log.isDebugEnabled()) { log.debug(sm.getString(lifecycleBase.setState, this, state)); } // 是否校验状态 if (check) { // Must have been triggered by one of the abstract methods (assume // code in this class is correct) // null is never a valid state // state不允许为null if (state null) { invalidTransition(null); // Unreachable code - here to stop eclipse complaining about // a possible NPE further down the method return; } // Any method can transition to failed // startInternal() permits STARTING_PREP to STARTING // stopInternal() permits STOPPING_PREP to STOPPING and FAILED to // STOPPING if (!(state LifecycleState.FAILED || (this.state LifecycleState.STARTING_PREP state LifecycleState.STARTING) || (this.state LifecycleState.STOPPING_PREP state LifecycleState.STOPPING) || (this.state LifecycleState.FAILED state LifecycleState.STOPPING))) { // No other transition permitted invalidTransition(state.name()); } } // 设置状态 this.state state; // 触发事件 String lifecycleEvent state.getLifecycleEvent(); if (lifecycleEvent ! null) { fireLifecycleEvent(lifecycleEvent, data); } }设置完 state 的状态之后就触发该状态的事件了通知事件监听器java/** * The list of registered LifecycleListeners for event notifications. */ private final ListLifecycleListener lifecycleListeners new CopyOnWriteArrayList(); protected void fireLifecycleEvent(String type, Object data) { LifecycleEvent event new LifecycleEvent(this, type, data); for (LifecycleListener listener : lifecycleListeners) { listener.lifecycleEvent(event); } }这里的 LifecycleListener 对象是在 Catalina 对象解析 server.xml 文件时就已经创建好并加到 lifecycleListeners 里的。这个不是特别重要就不细讲了。startjavaOverride public final synchronized void start() throws LifecycleException { // STARTING_PREP、STARTING和STARTED时将忽略start()逻辑 if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) || LifecycleState.STARTED.equals(state)) { if (log.isDebugEnabled()) { Exception e new LifecycleException(); log.debug(sm.getString(lifecycleBase.alreadyStarted, toString()), e); } else if (log.isInfoEnabled()) { log.info(sm.getString(lifecycleBase.alreadyStarted, toString())); } return; } // NEW状态时执行init()方法 if (state.equals(LifecycleState.NEW)) { init(); } // FAILED状态时执行stop()方法 else if (state.equals(LifecycleState.FAILED)) { stop(); } // 不是INITIALIZED和STOPPED时则说明是非法的操作 else if (!state.equals(LifecycleState.INITIALIZED) !state.equals(LifecycleState.STOPPED)) { invalidTransition(Lifecycle.BEFORE_START_EVENT); } try { // start前的状态设置 setStateInternal(LifecycleState.STARTING_PREP, null, false); // start逻辑抽象方法由组件自行实现 startInternal(); // start过程中可能因为某些原因失败这时需要stop操作 if (state.equals(LifecycleState.FAILED)) { // This is a controlled failure. The component put itself into the // FAILED state so call stop() to complete the clean-up. stop(); } else if (!state.equals(LifecycleState.STARTING)) { // Shouldnt be necessary but acts as a check that sub-classes are // doing what they are supposed to. invalidTransition(Lifecycle.AFTER_START_EVENT); } else { // 设置状态为STARTED setStateInternal(LifecycleState.STARTED, null, false); } } catch (Throwable t) { // This is an uncontrolled failure so put the component into the // FAILED state and throw an exception. ExceptionUtils.handleThrowable(t); setStateInternal(LifecycleState.FAILED, null, false); throw new LifecycleException(sm.getString(lifecycleBase.startFail, toString()), t); } }stopjavaOverride public final synchronized void stop() throws LifecycleException { // STOPPING_PREP、STOPPING和STOPPED时将忽略stop()的执行 if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) || LifecycleState.STOPPED.equals(state)) { if (log.isDebugEnabled()) { Exception e new LifecycleException(); log.debug(sm.getString(lifecycleBase.alreadyStopped, toString()), e); } else if (log.isInfoEnabled()) { log.info(sm.getString(lifecycleBase.alreadyStopped, toString())); } return; } // NEW状态时直接将状态变更为STOPPED if (state.equals(LifecycleState.NEW)) { state LifecycleState.STOPPED; return; } // stop()的执行必须要是STARTED和FAILED if (!state.equals(LifecycleState.STARTED) !state.equals(LifecycleState.FAILED)) { invalidTransition(Lifecycle.BEFORE_STOP_EVENT); } try { // FAILED时直接触发BEFORE_STOP_EVENT事件 if (state.equals(LifecycleState.FAILED)) { // Dont transition to STOPPING_PREP as that would briefly mark the // component as available but do ensure the BEFORE_STOP_EVENT is // fired fireLifecycleEvent(BEFORE_STOP_EVENT, null); } else { // 设置状态为STOPPING_PREP setStateInternal(LifecycleState.STOPPING_PREP, null, false); } // stop逻辑抽象方法组件自行实现 stopInternal(); // Shouldnt be necessary but acts as a check that sub-classes are // doing what they are supposed to. if (!state.equals(LifecycleState.STOPPING) !state.equals(LifecycleState.FAILED)) { invalidTransition(Lifecycle.AFTER_STOP_EVENT); } // 设置状态为STOPPED setStateInternal(LifecycleState.STOPPED, null, false); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); setStateInternal(LifecycleState.FAILED, null, false); throw new LifecycleException(sm.getString(lifecycleBase.stopFail,toString()), t); } finally { if (this instanceof Lifecycle.SingleUse) { // Complete stop process first setStateInternal(LifecycleState.STOPPED, null, false); destroy(); } } }destoryjavaOverride public final synchronized void destroy() throws LifecycleException { // FAILED状态时直接触发stop()逻辑 if (LifecycleState.FAILED.equals(state)) { try { // Triggers clean-up stop(); } catch (LifecycleException e) { // Just log. Still want to destroy. log.warn(sm.getString( lifecycleBase.destroyStopFail, toString()), e); } } // DESTROYING和DESTROYED时忽略destroy的执行 if (LifecycleState.DESTROYING.equals(state) || LifecycleState.DESTROYED.equals(state)) { if (log.isDebugEnabled()) { Exception e new LifecycleException(); log.debug(sm.getString(lifecycleBase.alreadyDestroyed, toString()), e); } else if (log.isInfoEnabled() !(this instanceof Lifecycle.SingleUse)) { // Rather than have every component that might need to call // destroy() check for SingleUse, dont log an info message if // multiple calls are made to destroy() log.info(sm.getString(lifecycleBase.alreadyDestroyed, toString())); } return; } // 非法状态判断 if (!state.equals(LifecycleState.STOPPED) !state.equals(LifecycleState.FAILED) !state.equals(LifecycleState.NEW) !state.equals(LifecycleState.INITIALIZED)) { invalidTransition(Lifecycle.BEFORE_DESTROY_EVENT); } try { // destroy前状态设置 setStateInternal(LifecycleState.DESTROYING, null, false); // 抽象方法组件自行实现 destroyInternal(); // destroy后状态设置 setStateInternal(LifecycleState.DESTROYED, null, false); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); setStateInternal(LifecycleState.FAILED, null, false); throw new LifecycleException( sm.getString(lifecycleBase.destroyFail,toString()), t); } }用了什么设计模式从上述源码看得出来LifecycleBase是使用了状态机模板模式来实现的。模板方法有下面这几个java// 初始化方法 protected abstract void initInternal() throws LifecycleException; // 启动方法 protected abstract void startInternal() throws LifecycleException; // 停止方法 protected abstract void stopInternal() throws LifecycleException; // 销毁方法 protected abstract void destroyInternal() throws LifecycleException;组件拓展管理MX和MBean为什么要了解JMX我们在上文中讲Lifecycle和相关组件时你会发现其实还设计一块就是左侧的JMX和MBean的实现即LifecycleMBeanBase.什么是JMX和MBeanJMX是java1.5中引入的新特性。JMX全称为“Java Management Extension”即Java管理扩展。JMX(Java Management Extensions)是一个为应用程序植入管理功能的框架。JMX是一套标准的代理和服务实际上用户可以在任何Java应用程序中使用这些代理和服务实现管理。它使用了最简单的一类javaBean使用有名的MBean其内部包含了数据信息这些信息可能是程序配置信息、模块信息、系统信息、统计信息等。MBean可以操作可读可写的属性、直接操作某些函数。应用场景中间件软件WebLogic的管理页面就是基于JMX开发的而JBoss则整个系统都基于JMX构架我们今天讲的Tomcat也是基于JMX开发而来的。我们看下JMX的结构Probe Level负责资源的检测获取信息包含MBeans通常也叫做Instrumentation Level。MX管理构件MBean分为四种形式分别是标准管理构件Standard MBean、动态管理构件Dynamic MBean、开放管理构件(Open Mbean)和模型管理构件(Model MBean)。The Agent Level或者叫做MBean Server代理服务器是JMX的核心连接Mbeans和远程监控程序。Remote Management Level通过connectors和adaptors来远程操作MBean Server。JMX使用案例上节只是引入和相关概念这是不够的你依然需要一个案例来帮助你理解JMX是如何工作的。基于JMX的监控例子ServerImpl - 我们模拟的某个服务器ServerImpl状态javapublic class ServerImpl { public final long startTime; public ServerImpl() { startTime System.currentTimeMillis(); } }由于MXBean规定标准MBean也要实现一个接口其所有向外界公开的方法都要在该接口中声明否则管理系统就不能从中获取信息。此外该接口的命名有一定的规范在标准MBean类名后加上MBean后缀。这里的标准MBean类就是ServerMonitor所以其对应的接口就应该是ServerMonitorMBean。因此ServerMonitorMBean的实现如下javapublic interface ServerMonitorMBean { public long getUpTime(); }使用ServerMonitor类来监测ServerImpl的状态实现如下javapublic class ServerMonitor implements ServerMonitorMBean { private final ServerImpl target; public ServerMonitor(ServerImpl target) { this.target target; } Override public long getUpTime() { return System.currentTimeMillis() - target.startTime; } }对于管理系统来讲这些MBean中公开的方法最终会被JMX转换为属性Attribute、监听Listener和调用Invoke的概念。下面代码中Main类的manage方法就模拟了管理程序是如何获取监测到的属性并表现监测结果。javaimport javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; public class Main { private static ObjectName objectName; private static MBeanServer mBeanServer; public static void main(String[] args) throws Exception { init(); manage(); } private static void init() throws Exception { ServerImpl serverImpl new ServerImpl(); ServerMonitor serverMonitor new ServerMonitor(serverImpl); mBeanServer MBeanServerFactory.createMBeanServer(); objectName new ObjectName(objectName:idServerMonitor1); // 注册到MBeanServer mBeanServer.registerMBean(serverMonitor, objectName); } private static void manage() throws Exception { // 获取属性值 long upTime (Long)mBeanServer.getAttribute(objectName, UpTime); System.out.println(upTime); } }整体流程如上步骤就能让你理解常见的Jconsole是如何通过JMX获取属性对象等监控信息的了。基于JMX的HTMLAdapter案例上面例子还没有体现adapter展示比如上述信息在HTML页面中展示出来再看一个例子我们的管理目标javapublic class ControlTarget { private long width; private long length; public ControlTarget( long width, long length) { this.width width; this.length length; } public long getWidth() { return width; } public long getLength() { return length; } }根据标准MBean类抽象出符合规范的MBean类的接口并修改标准MBean类实现该接口。javapublic interface ControlImplMBean { public long getLength(); public long getWidth(); public long getArea(); public double getLengthWidthRatio(); }根据需求创建管理目标程序的类其中包含操纵和获取目标程序特性的方法。这个类就是标准MBean类。javapublic class ControlImpl implements ControlImplMBean { private ControlTarget target; public ControlImpl(ControlTarget target) { this.target target; } Override public long getLength() { return target.getLength(); } Override public long getWidth() { return target.getWidth(); } Override public long getArea() { return target.getLength() * target.getWidth(); } Override public double getLengthWidthRatio() { return target.getLength() * 1.0f / target.getWidth(); } }创建MBean的代理类代理中包含创建MBeanServer、生成ObjectName、注册MBean、表现MBeanjavaimport com.sun.jdmk.comm.HtmlAdaptorServer; import javax.management.*; public class ControlImplAgent { public static void main(String[] args) throws MalformedObjectNameException, NullPointerException, InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { // 创建MBeanServer MBeanServer server MBeanServerFactory.createMBeanServer(); // 为MBean创建ObjectName ObjectName controlImplName new ObjectName(controlImpl:namefirstOne); // 注册MBean到Server中 server.registerMBean(new ControlImpl(new ControlTarget(50, 200)), controlImplName); // 表现MBean(一种方式) ObjectName adapterName new ObjectName(ControlImpl:namehtmladapter,port8082); HtmlAdaptorServer adapter new HtmlAdaptorServer(); server.registerMBean(adapter, adapterName); adapter.start(); //adapter.stop(); } }打开相关页面PS相关Adapter可以通过这里下载https://download.csdn.net/download/com_ma/10379741点击最后一个链接Tomcat如何通过JMX实现组件管理在简单理解了JMX概念和案例之后我们便可以开始学习Tomcat基于JMX的实现了。上述图中我们看下相关的类的用途MBeanRegistrationJava JMX框架提供的注册MBean的接口引入此接口是为了便于使用JMX提供的管理功能JmxEnabled: 此接口由组件实现这些组件在创建时将注册到MBean服务器在销毁时将注销这些组件。它主要是由实现生命周期的组件来实现的但并不是专门为它们实现的。LifecycleMBeanBaseTomcat提供的对MBeanRegistration的抽象实现类运用抽象模板模式将所有容器统一注册到JMX此外ContainerBase、StandardServer、StandardService、WebappLoader、Connector、StandardContext、StandardEngine、StandardHost、StandardWrapper等容器都继承了LifecycleMBeanBase因此这些容器都具有了同样的生命周期并可以通过JMX进行管理。MBeanRegistration理解MBeanRegistration主要在于:两块内容registered 和 unregistered两类方法before和afterjavapublic interface MBeanRegistration { // 在注册之前执行的方法如果发生异常MBean不会注册到MBean Server中 public ObjectName preRegister(MBeanServer server, ObjectName name) throws java.lang.Exception; // 在注册之后执行的方法比如注册失败提供报错信息 public void postRegister(Boolean registrationDone); // 在卸载前执行的方法 public void preDeregister() throws java.lang.Exception ; // 在执行卸载之后的方法 public void postDeregister(); }JmxEnabled理解JmxEnabled在设计上它引一个域Domain对注册的MBeans进行隔离这个域类似于MBean上层的命名空间一样。javapublic interface JmxEnabled extends MBeanRegistration { // 获取MBean所属于的Domain String getDomain(); // 设置Domain void setDomain(String domain); // 获取MBean的名字 ObjectName getObjectName(); }LifecycleMBeanBase这样理解LifecycleMBeanBase时你便知道它包含两块一个是Lifecycle的接口实现一个是Jmx接口封装实现。从它实现的类继承和实现关系便能看出javapublic abstract class LifecycleMBeanBase extends LifecycleBase implements JmxEnabled { }JmxEnabled的接口实现Domain和mBeanName相关代码很简单不做详解java/* Cache components of the MBean registration. */ private String domain null; private ObjectName oname null; Deprecated protected MBeanServer mserver null; /** * Specify the domain under which this component should be registered. Used * with components that cannot (easily) navigate the component hierarchy to * determine the correct domain to use. */ Override public final void setDomain(String domain) { this.domain domain; } /** * Obtain the domain under which this component will be / has been * registered. */ Override public final String getDomain() { if (domain null) { domain getDomainInternal(); } if (domain null) { domain Globals.DEFAULT_MBEAN_DOMAIN; } return domain; } /** * Method implemented by sub-classes to identify the domain in which MBeans * should be registered. * * return The name of the domain to use to register MBeans. */ protected abstract String getDomainInternal(); /** * Obtain the name under which this component has been registered with JMX. */ Override public final ObjectName getObjectName() { return oname; } /** * Allow sub-classes to specify the key properties component of the * {link ObjectName} that will be used to register this component. * * return The string representation of the key properties component of the * desired {link ObjectName} */