九江煎堆 發表於 2026-4-23 09:00:00

Tomcat组件管理源码详解

<h2 id="生命周期管理lifecycle">生命周期管理:LifeCycle</h2>
<blockquote>
<p>我从以下几方面,帮助你构建基于上下文的知识体系和理解为什么要理解组件的生命周期管理(LifeCycle)</p>
</blockquote>
<ul>
<li>Server及其它组件</li>
</ul>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603081058757.png" alt="" loading="lazy"></p>
<ul>
<li>Server后续组件生命周期及初始化</li>
</ul>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603081100344.png" alt="" loading="lazy"></p>
<ul>
<li>Server的依赖结构</li>
</ul>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603081100692.png" alt="" loading="lazy"></p>
<h3 id="lifecycle接口">LifeCycle接口</h3>
<blockquote>
<p>理解Lifecycle主要有两点:第一是三类接口方法;第二是状态机。</p>
</blockquote>
<h3 id="一个标准的lifecycle有哪些方法">一个标准的LifeCycle有哪些方法?</h3>
<p>分三类去看:</p>
<pre><code class="language-java">public 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();
}
</code></pre>
<h4 id="lifecycle状态机有哪些状态">LifeCycle状态机有哪些状态?</h4>
<p>Tomcat 给各个组件定义了一些生命周期中的状态</p>
<ul>
<li>在枚举类 LifecycleState 里</li>
</ul>
<pre><code class="language-java">public 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;
    }
    ……
}
</code></pre>
<ul>
<li>它们之间的关系是怎么样的呢?</li>
</ul>
<p>在Lifecycle.java源码中有相关的注释:</p>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603081101459.png" alt="" loading="lazy"></p>
<p>看不太清楚的可以看下图:</p>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603081101303.jpeg" alt="" loading="lazy"></p>
<h3 id="lifecyclebase---lifecycle的基本实现">LifecycleBase - LifeCycle的基本实现</h3>
<blockquote>
<p>LifecycleBase是Lifecycle的基本实现。</p>
</blockquote>
<h4 id="监听器相关">监听器相关</h4>
<p>生命周期监听器保存在一个线程安全的<strong>CopyOnWriteArrayList</strong>中。所以add和remove都是直接调用此List的相应方法。 findLifecycleListeners返回的是一个数组,为了线程安全,所以这儿会生成一个新数组。</p>
<pre><code class="language-java">private final List&lt;LifecycleListener&gt; lifecycleListeners = new CopyOnWriteArrayList&lt;&gt;();

@Override
public void addLifecycleListener(LifecycleListener listener) {
    lifecycleListeners.add(listener);
}
@Override
public LifecycleListener[] findLifecycleListeners() {
    return lifecycleListeners.toArray(new LifecycleListener);
}
@Override
public void removeLifecycleListener(LifecycleListener listener) {
    lifecycleListeners.remove(listener);
}
</code></pre>
<h4 id="生命周期相关">生命周期相关</h4>
<ul>
<li>init</li>
</ul>
<pre><code class="language-java">@Override
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);
    }
}
</code></pre>
<p>我们再来看看invalidTransition方法,该方法直接抛出异常。</p>
<pre><code class="language-java">private void invalidTransition(String type) throws LifecycleException {
    String msg = sm.getString("lifecycleBase.invalidTransition", type,
            toString(), state);
    throw new LifecycleException(msg);
}
</code></pre>
<p>setStateInternal方法用于维护状态,同时在状态转换成功之后触发事件。为了状态的可见性,所以state声明为volatile类型的。</p>
<pre><code class="language-java">private 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 &amp;&amp;
                        state == LifecycleState.STARTING) ||
                (this.state == LifecycleState.STOPPING_PREP &amp;&amp;
                        state == LifecycleState.STOPPING) ||
                (this.state == LifecycleState.FAILED &amp;&amp;
                        state == LifecycleState.STOPPING))) {
            // No other transition permitted
            invalidTransition(state.name());
      }
    }

    // 设置状态
    this.state = state;
    // 触发事件
    String lifecycleEvent = state.getLifecycleEvent();
    if (lifecycleEvent != null) {
      fireLifecycleEvent(lifecycleEvent, data);
    }
}
</code></pre>
<p>设置完 state 的状态之后,就触发该状态的事件了,通知事件监听器</p>
<pre><code class="language-java">/**
* The list of registered LifecycleListeners for event notifications.
*/
private final List&lt;LifecycleListener&gt; lifecycleListeners = new CopyOnWriteArrayList&lt;&gt;();


protected void fireLifecycleEvent(String type, Object data) {
    LifecycleEvent event = new LifecycleEvent(this, type, data);
    for (LifecycleListener listener : lifecycleListeners) {
      listener.lifecycleEvent(event);
    }
}
</code></pre>
<p>这里的 LifecycleListener 对象是在 Catalina 对象解析 server.xml 文件时就已经创建好并加到 lifecycleListeners 里的。这个不是特别重要就不细讲了。</p>
<ul>
<li>start</li>
</ul>
<pre><code class="language-java">@Override
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) &amp;&amp;
            !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)) {
            // Shouldn't 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);
    }
}
</code></pre>
<ul>
<li>stop</li>
</ul>
<pre><code class="language-java">@Override
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) &amp;&amp; !state.equals(LifecycleState.FAILED)) {
      invalidTransition(Lifecycle.BEFORE_STOP_EVENT);
    }

    try {
      // `FAILED`时,直接触发BEFORE_STOP_EVENT事件
      if (state.equals(LifecycleState.FAILED)) {
            // Don't 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();

      // Shouldn't be necessary but acts as a check that sub-classes are
      // doing what they are supposed to.
      if (!state.equals(LifecycleState.STOPPING) &amp;&amp; !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();
      }
    }
}
</code></pre>
<ul>
<li>destory</li>
</ul>
<pre><code class="language-java">@Override
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() &amp;&amp; !(this instanceof Lifecycle.SingleUse)) {
            // Rather than have every component that might need to call
            // destroy() check for SingleUse, don't log an info message if
            // multiple calls are made to destroy()
            log.info(sm.getString("lifecycleBase.alreadyDestroyed", toString()));
      }

      return;
    }

    // 非法状态判断
    if (!state.equals(LifecycleState.STOPPED) &amp;&amp;
            !state.equals(LifecycleState.FAILED) &amp;&amp;
            !state.equals(LifecycleState.NEW) &amp;&amp;
            !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);
    }
}
</code></pre>
<h4 id="用了什么设计模式">用了什么设计模式?</h4>
<p>从上述源码看得出来,LifecycleBase是使用了<strong>状态机</strong>+<strong>模板模式</strong>来实现的。模板方法有下面这几个:</p>
<pre><code class="language-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;
</code></pre>
<h2 id="组件拓展管理mx和mbean">组件拓展管理:MX和MBean</h2>
<h3 id="为什么要了解jmx">为什么要了解JMX</h3>
<p>我们在上文中讲Lifecycle和相关组件时,你会发现其实还设计一块就是左侧的JMX和MBean的实现,即LifecycleMBeanBase.</p>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603081103963.jpeg" alt="" loading="lazy"></p>
<h3 id="什么是jmx和mbean">什么是JMX和MBean</h3>
<blockquote>
<p>JMX是java1.5中引入的新特性。JMX全称为“Java Management Extension”,即Java管理扩展。</p>
</blockquote>
<p>JMX(Java Management Extensions)是一个为应用程序植入管理功能的框架。JMX是一套标准的代理和服务,实际上,用户可以在任何Java应用程序中使用这些代理和服务实现管理。它使用了最简单的一类javaBean,使用有名的MBean,其内部包含了数据信息,这些信息可能是程序配置信息、模块信息、系统信息、统计信息等。MBean可以操作可读可写的属性、直接操作某些函数。</p>
<p><strong>应用场景</strong>:中间件软件WebLogic的管理页面就是基于JMX开发的,而JBoss则整个系统都基于JMX构架,我们今天讲的Tomcat也是基于JMX开发而来的。</p>
<p>我们看下<strong>JMX的结构</strong></p>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603081104343.png" alt="" loading="lazy"></p>
<ul>
<li><strong>Probe Level</strong> 负责资源的检测(获取信息),包含MBeans,通常也叫做Instrumentation Level。MX管理构件(MBean)分为四种形式,分别是标准管理构件(Standard MBean)、动态管理构件(Dynamic MBean)、开放管理构件(Open Mbean)和模型管理构件(Model MBean)。</li>
<li><strong>The Agent Level</strong> 或者叫做MBean Server(代理服务器),是JMX的核心,连接Mbeans和远程监控程序。</li>
<li><strong>Remote Management Level</strong> 通过connectors和adaptors来远程操作MBean Server。</li>
</ul>
<h3 id="jmx使用案例">JMX使用案例</h3>
<blockquote>
<p>上节只是引入和相关概念,这是不够的,你依然需要一个案例来帮助你理解JMX是如何工作的。</p>
</blockquote>
<h4 id="基于jmx的监控例子">基于JMX的监控例子</h4>
<ul>
<li>ServerImpl - 我们模拟的某个服务器ServerImpl状态</li>
</ul>
<pre><code class="language-java">public class ServerImpl {
    public final long startTime;
    public ServerImpl() {
      startTime = System.currentTimeMillis();
    }
}
</code></pre>
<ul>
<li>由于MXBean规定,标准MBean也要实现一个接口,其所有向外界公开的方法都要在该接口中声明,否则管理系统就不能从中获取信息。此外,该接口的命名有一定的规范:在标准MBean类名后加上MBean后缀。这里的标准MBean类就是ServerMonitor,所以其对应的接口就应该是ServerMonitorMBean。因此ServerMonitorMBean的实现如下</li>
</ul>
<pre><code class="language-java">public interface ServerMonitorMBean {
        public long getUpTime();
}
</code></pre>
<ul>
<li>使用ServerMonitor类来监测ServerImpl的状态,实现如下</li>
</ul>
<pre><code class="language-java">public class ServerMonitor implements ServerMonitorMBean {
    private final ServerImpl target;
    public ServerMonitor(ServerImpl target) {
      this.target = target;
    }

    @Override
    public long getUpTime() {
      return System.currentTimeMillis() - target.startTime;
    }
}
</code></pre>
<ul>
<li>对于管理系统来讲,这些MBean中公开的方法,最终会被JMX转换为属性(Attribute)、监听(Listener)和调用(Invoke)的概念。下面代码中Main类的manage方法就模拟了管理程序是如何获取监测到的属性,并表现监测结果。</li>
</ul>
<pre><code class="language-java">import 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:id=ServerMonitor1");

      // 注册到MBeanServer
      mBeanServer.registerMBean(serverMonitor, objectName);
    }

    private static void manage() throws Exception {
      // 获取属性值
      long upTime = (Long)mBeanServer.getAttribute(objectName, "UpTime");
      System.out.println(upTime);
    }
}
</code></pre>
<ul>
<li>整体流程</li>
</ul>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603081105965.jpeg" alt="" loading="lazy"></p>
<blockquote>
<p>如上步骤就能让你理解常见的Jconsole是如何通过JMX获取属性,对象等监控信息的了。</p>
</blockquote>
<h4 id="基于jmx的htmladapter案例">基于JMX的HTMLAdapter案例</h4>
<blockquote>
<p>上面例子,还没有体现adapter展示,比如上述信息在HTML页面中展示出来,再看一个例子</p>
</blockquote>
<ul>
<li>我们的管理目标</li>
</ul>
<pre><code class="language-java">public 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;
        }
}
</code></pre>
<ul>
<li>根据标准MBean类抽象出符合规范的MBean类的接口,并修改标准MBean类实现该接口。</li>
</ul>
<pre><code class="language-java">public interface ControlImplMBean {
        public long getLength();
        public long getWidth();
        public long getArea();
        public double getLengthWidthRatio();
}
</code></pre>
<ul>
<li>根据需求,创建管理(目标程序)的类,其中包含操纵和获取(目标程序)特性的方法。这个类就是标准MBean类。</li>
</ul>
<pre><code class="language-java">public 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() {
                returntarget.getLength() * 1.0f / target.getWidth();
        }
}
</code></pre>
<ul>
<li>创建MBean的代理类,代理中包含创建MBeanServer、生成ObjectName、注册MBean、表现MBean</li>
</ul>
<pre><code class="language-java">import 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:name=firstOne");

      // 注册MBean到Server中
      server.registerMBean(new ControlImpl(new ControlTarget(50, 200)), controlImplName);

      // 表现MBean(一种方式)
      ObjectName adapterName = new ObjectName("ControlImpl:name=htmladapter,port=8082");
      HtmlAdaptorServer adapter = new HtmlAdaptorServer();
      server.registerMBean(adapter, adapterName);

      adapter.start();
      //adapter.stop();
    }

}
</code></pre>
<ul>
<li>打开相关页面</li>
</ul>
<p>PS:相关Adapter可以通过这里下载https://download.csdn.net/download/com_ma/10379741</p>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603081105848.jpeg" alt="" loading="lazy"></p>
<p>点击最后一个链接</p>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603081106051.jpeg" alt="" loading="lazy"></p>
<h3 id="tomcat如何通过jmx实现组件管理">Tomcat如何通过JMX实现组件管理</h3>
<blockquote>
<p>在简单理解了JMX概念和案例之后,我们便可以开始学习Tomcat基于JMX的实现了。</p>
</blockquote>
<p><img src="https://seven97-blog.oss-cn-hangzhou.aliyuncs.com/imgs/202603081106913.jpeg" alt="" loading="lazy"></p>
<p>上述图中,我们看下相关的类的用途</p>
<ul>
<li>
<p><code>MBeanRegistration</code>:Java JMX框架提供的注册MBean的接口,引入此接口是为了便于使用JMX提供的管理功能;</p>
</li>
<li>
<p><code>JmxEnabled</code>: 此接口由组件实现,这些组件在创建时将注册到MBean服务器,在销毁时将注销这些组件。它主要是由实现生命周期的组件来实现的,但并不是专门为它们实现的。</p>
</li>
<li>
<p><code>LifecycleMBeanBase</code>:Tomcat提供的对MBeanRegistration的抽象实现类,运用抽象模板模式将所有容器统一注册到JMX;</p>
</li>
</ul>
<p>此外,ContainerBase、StandardServer、StandardService、WebappLoader、Connector、StandardContext、StandardEngine、StandardHost、StandardWrapper等容器都继承了LifecycleMBeanBase,因此这些容器都具有了同样的生命周期并可以通过JMX进行管理。</p>
<h4 id="mbeanregistration">MBeanRegistration</h4>
<p>理解MBeanRegistration主要在于:</p>
<ul>
<li>两块内容:registered 和 unregistered</li>
<li>两类方法:before和after</li>
</ul>
<pre><code class="language-java">public 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();

}
</code></pre>
<h4 id="jmxenabled">JmxEnabled</h4>
<p>理解JmxEnabled:在设计上它引一个域(Domain)对注册的MBeans进行隔离,这个域类似于MBean上层的命名空间一样。</p>
<pre><code class="language-java">public interface JmxEnabled extends MBeanRegistration {

    // 获取MBean所属于的Domain
    String getDomain();

    // 设置Domain
    void setDomain(String domain);

    // 获取MBean的名字
    ObjectName getObjectName();
}
</code></pre>
<h4 id="lifecyclembeanbase">LifecycleMBeanBase</h4>
<p>这样理解LifecycleMBeanBase时,你便知道它包含两块,一个是Lifecycle的接口实现,一个是Jmx接口封装实现。</p>
<p>从它实现的类继承和实现关系便能看出:</p>
<pre><code class="language-java">public abstract class LifecycleMBeanBase extends LifecycleBase
      implements JmxEnabled {

}
</code></pre>
<h5 id="jmxenabled的接口实现">JmxEnabled的接口实现</h5>
<ul>
<li>Domain和mBeanName相关,代码很简单,不做详解</li>
</ul>
<pre><code class="language-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.
*
* @returnThe 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.
*
* @returnThe string representation of the key properties component of the
*          desired {@link ObjectName}
*/
protected abstract String getObjectNameKeyProperties();
</code></pre>
<ul>
<li>注册和卸载的相关方法</li>
</ul>
<pre><code class="language-java">/**
* Utility method to enable sub-classes to easily register additional
* components that don't implement {@link JmxEnabled} with an MBean server.
* &lt;br&gt;
* Note: This method should only be used once {@link #initInternal()} has
* been called and before {@link #destroyInternal()} has been called.
*
* @param obj                     The object the register
* @param objectNameKeyProperties   The key properties component of the
*                                  object name to use to register the
*                                  object
*
* @returnThe name used to register the object
*/
protected final ObjectName register(Object obj,
      String objectNameKeyProperties) {

    // Construct an object name with the right domain
    StringBuilder name = new StringBuilder(getDomain());
    name.append(':');
    name.append(objectNameKeyProperties);

    ObjectName on = null;

    try {
      on = new ObjectName(name.toString());
      Registry.getRegistry(null, null).registerComponent(obj, on, null);
    } catch (MalformedObjectNameException e) {
      log.warn(sm.getString("lifecycleMBeanBase.registerFail", obj, name),
                e);
    } catch (Exception e) {
      log.warn(sm.getString("lifecycleMBeanBase.registerFail", obj, name),
                e);
    }

    return on;
}


/**
* Utility method to enable sub-classes to easily unregister additional
* components that don't implement {@link JmxEnabled} with an MBean server.
* &lt;br&gt;
* Note: This method should only be used once {@link #initInternal()} has
* been called and before {@link #destroyInternal()} has been called.
*
* @param objectNameKeyProperties   The key properties component of the
*                                  object name to use to unregister the
*                                  object
*/
protected final void unregister(String objectNameKeyProperties) {
    // Construct an object name with the right domain
    StringBuilder name = new StringBuilder(getDomain());
    name.append(':');
    name.append(objectNameKeyProperties);
    Registry.getRegistry(null, null).unregisterComponent(name.toString());
}


/**
* Utility method to enable sub-classes to easily unregister additional
* components that don't implement {@link JmxEnabled} with an MBean server.
* &lt;br&gt;
* Note: This method should only be used once {@link #initInternal()} has
* been called and before {@link #destroyInternal()} has been called.
*
* @param on    The name of the component to unregister
*/
protected final void unregister(ObjectName on) {
    Registry.getRegistry(null, null).unregisterComponent(on);
}


/**
* Not used - NOOP.
*/
@Override
public final void postDeregister() {
    // NOOP
}


/**
* Not used - NOOP.
*/
@Override
public final void postRegister(Boolean registrationDone) {
    // NOOP
}


/**
* Not used - NOOP.
*/
@Override
public final void preDeregister() throws Exception {
    // NOOP
}


/**
* Allows the object to be registered with an alternative
* {@link MBeanServer} and/or {@link ObjectName}.
*/
@Override
public final ObjectName preRegister(MBeanServer server, ObjectName name)
      throws Exception {

    this.mserver = server;
    this.oname = name;
    this.domain = name.getDomain().intern();

    return oname;
}
</code></pre>
<h5 id="lifecyclebase相关接口">LifecycleBase相关接口</h5>
<p>这样你就知道这里抽象出的LifecycleBase如下两个方法的用意,就是为了注册和卸载MBean</p>
<pre><code class="language-java">/**
注册MBean
*/
@Override
protected void initInternal() throws LifecycleException {
    // If oname is not null then registration has already happened via
    // preRegister().
    if (oname == null) {
      mserver = Registry.getRegistry(null, null).getMBeanServer();

      oname = register(this, getObjectNameKeyProperties());
    }
}


/**
卸载MBean
*/
@Override
protected void destroyInternal() throws LifecycleException {
    unregister(oname);
}
</code></pre>


</div>
<div id="MySignature" role="contentinfo">
    <p>本文来自在线网站:seven的菜鸟成长之路,作者:seven,转载请注明原文链接:www.seven97.top</p><br><br>
来源:https://www.cnblogs.com/sevencoding/p/19887304
頁: [1]
查看完整版本: Tomcat组件管理源码详解