zoukankan      html  css  js  c++  java
  • Tomcat中组件的生命周期管理(三)

    本文主要目的是自定义举例分析Catalina内部生命周期管理的运作方式以及拿内部具体源码来具体分析

    假设我们有一台电脑由主机(我们用cpu表示)和显示器构成,那么我们要运用上篇文章学到的内容,来管理整个电脑的启动和关闭,先看我们对类的定义。

    在本例中我们对Lifecycle类进行了部分删减,只保留了关于startstop的相关事件。

    • Lifecycle

        public interface Lifecycle {
      
            // ----------------------------------------------------- Manifest Constants
            public static final String START_EVENT = "start";
        
        
            /**
             * The LifecycleEvent type for the "component before start" event.
             */
            public static final String BEFORE_START_EVENT = "before_start";
        
        
            /**
             * The LifecycleEvent type for the "component after start" event.
             */
            public static final String AFTER_START_EVENT = "after_start";
        
        
            /**
             * The LifecycleEvent type for the "component stop" event.
             */
            public static final String STOP_EVENT = "stop";
        
        
            /**
             * The LifecycleEvent type for the "component before stop" event.
             */
            public static final String BEFORE_STOP_EVENT = "before_stop";
        
        
            /**
             * The LifecycleEvent type for the "component after stop" event.
             */
            public static final String AFTER_STOP_EVENT = "after_stop";
        
        
            // --------------------------------------------------------- Public Methods
        
        
          
            public void addLifecycleListener(LifecycleListener listener);
        
        
            public LifecycleListener[] findLifecycleListeners();
        
        
            public void removeLifecycleListener(LifecycleListener listener);
        
        
            public void start() throws LifecycleException;
        
        
            public void stop() throws LifecycleException;
      
        }
      

    同样LifecycleBase类也只保留了start,stop相关方法。

    • LifecycleBase

        public abstract class LifeCycleBase implements Lifecycle {
      
            private LifecycleSupport support = new LifecycleSupport(this);
        	//组件名称
            public String name;
        
        
            @Override
            public void addLifecycleListener(LifecycleListener listener) {
                support.addLifecycleListener(listener);
            }
        
            @Override
            public LifecycleListener[] findLifecycleListeners() {
                return support.findLifecycleListeners();
            }
        
            @Override
            public void removeLifecycleListener(LifecycleListener listener) {
                support.removeLifecycleListener(listener);
            }
        
            protected void fireLifecycleEvent(String type, Object data) {
                support.fireLifecycleEvent(type, data);
            }
        
        
            protected abstract void startInternal() throws LifecycleException;
        
            @Override
            public void start() throws LifecycleException {
                System.out.println(name + " 准备启动");
                fireLifecycleEvent(Lifecycle.BEFORE_START_EVENT, null);
                System.out.println(name + " 正在启动");
                fireLifecycleEvent(Lifecycle.START_EVENT, null);
                startInternal();
                System.out.println(name + " 启动完毕");
                fireLifecycleEvent(Lifecycle.AFTER_START_EVENT, null);
        
            }
        
            protected abstract void stopInternal() throws LifecycleException;
        
            @Override
            public void stop() throws LifecycleException {
                System.out.println(name + " 准备关闭");
                fireLifecycleEvent(Lifecycle.BEFORE_STOP_EVENT, null);
                System.out.println(name + " 正在关闭");
                stopInternal();
                fireLifecycleEvent(Lifecycle.STOP_EVENT, null);
                System.out.println(name + " 关闭完毕");
                fireLifecycleEvent(Lifecycle.AFTER_STOP_EVENT, null);
            }
      
        }
      

    电脑组成部件 CPU定义

    • CPU

        public class CPU extends LifeCycleBase {
            @Override
            public void startInternal() throws LifecycleException {
                System.out.println(super.name + "在启动过程中 负载达到了100%!");
            }
            @Override
            public void stopInternal() throws LifecycleException {
                System.out.println(name + "在关闭过程中 负载下降到了1%!");
            }
        
            public CPU(String name) {
                super.name = name;
            }
        }
      

    电脑组成部件 Monitor定义

    • Monitor

        public class Monitor extends LifeCycleBase {
      
            @Override
            public void startInternal() throws LifecycleException {
                System.out.println(name + "在启动过程中 屏幕 很亮!");
            }
            @Override
            public void stopInternal() throws LifecycleException {
                System.out.println(name + "在关闭过程中 屏幕渐渐暗了下去");
            }
            public Monitor(String name) {
                super.name = name;
            }
        }
      

    电脑类的定义

    • Computer

        public class Computer extends LifeCycleBase {
      
            private CPU cpu ;
            private Monitor monitor;
        
            @Override
            public void startInternal() throws LifecycleException {
        
                System.out.println(name + "在启动过程中 需要先启动子组件");
                if (cpu != null) {
                    ((Lifecycle) cpu).start();
                }
                if (monitor != null) {
                    ((Lifecycle) monitor).start();
                }
            }
            @Override
            public void stopInternal() throws LifecycleException {
                System.out.println(name + "在关闭过程中  需要先关闭子组件");
                if (cpu != null) {
                    ((Lifecycle) cpu).stop();
                }
                if (monitor != null) {
                    ((Lifecycle) monitor).stop();
                }
            }
        
            public Computer(String name) {
                super.name = name;
            }
        
            public void setCpu(CPU cpu) {
                this.cpu = cpu;
            }
        
            public void setMonitor(Monitor monitor) {
                this.monitor = monitor;
            }
        }
      

    运行类代码

    public class MainClass {
    
        public static void main(String[] args) throws Exception {
    
            Computer computer = new Computer("电脑");
            CPU cpu = new CPU("CPU");
            Monitor monitor = new Monitor("显示器");
            computer.setCpu(cpu);
            computer.setMonitor(monitor);
    
            cpu.addLifecycleListener(new LifecycleListener() {
                @Override
                public void lifecycleEvent(LifecycleEvent event) {
                    if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
                        System.out.println("已经监听到 cpu正在准备启动");
                    }
                }
            });
    
            monitor.addLifecycleListener(new LifecycleListener() {
                @Override
                public void lifecycleEvent(LifecycleEvent event) {
                    if (event.getType().equals(Lifecycle.AFTER_STOP_EVENT)) {
                        System.out.println("已经监听到显示器 已经停止");
                    }
                }
            });
            //启动
            computer.start();
            System.out.println("------------------------------------------");
            computer.stop();
        }
    
    }
    

    运行结果

    电脑 准备启动
    电脑 正在启动
    电脑在启动过程中 需要先启动子组件
    CPU 准备启动
    已经监听到 cpu正在准备启动
    CPU 正在启动
    CPU在启动过程中 负载达到了100%!
    CPU 启动完毕
    显示器 准备启动
    显示器 正在启动
    显示器在启动过程中 屏幕 很亮!
    显示器 启动完毕
    电脑 启动完毕
    ------------------------------------------
    电脑 准备关闭
    电脑 正在关闭
    电脑在关闭过程中  需要先关闭子组件
    CPU 准备关闭
    CPU 正在关闭
    CPU在关闭过程中 负载下降到了1%!
    CPU 关闭完毕
    显示器 准备关闭
    显示器 正在关闭
    显示器在关闭过程中 屏幕渐渐暗了下去
    显示器 关闭完毕
    已经监听到显示器 已经停止
    电脑 关闭完毕
    

    从源码可以看到每个组件的启动都会调用父类的start()方法,而start()方法又会调用本类的startInternal()方法,stop方法类似。在父类的start()方法定义了一些组件共性的动作,而在startInternal()方法中定义了组件自己的特殊动作。并且每个组件都可以自行添加自己的监听器。从运行的代码可以看到,只要设置好每个组件的关系就可以统一管理每个组件的启动关闭了。Catalina中的生命周期管理的模式大概就是这样,下面我们找个具体的类来分析。

    我们主要分析start()方法相关,其他类似init(),stop(),destroy()方法都是类似的。我们从前面的文章可以知道Tomcat启动的时候是调用了Bootstrap类的main()方法,而main()方法中最后调用了Catalina类的start()方法,我们查看Catalina类的start()方法,其中

    getServer().start();
    

    这一步又调用了StandardServer类的start()方法,从这里就Catalina是最顶层组件,下面所有的组件都开始需要进行生命周期管理了。所以查看StandardServer类的定义

    public final class StandardServer extends LifecycleMBeanBase implements Server
    

    再查看LifecycleMBeanBase类的定义

    public abstract class LifecycleMBeanBase extends LifecycleBase implements MBeanRegistration
    

    我们在这里就看到了上文介绍的关键类LifecycleBase类。之所以有个LifecycleMBeanBase类横跨在这里主要是因为Tomcat要将组件纳入JMX管理,所以用这个类来实现,这个不再本文的讲解范围之内,所以暂时不讨论,可以当作组件直接继承LifecycleBase类。

    既然StandardServer类直接继承了LifecycleBase类,那么Catalina调用StandardServer类的start()方法就是调用LifecycleBase类的start()方法(这样的前提是StandardServer,LifecycleMBeanBase类中没有start()方法,实际上这2个类的确没有实现start()方法)。上篇文章已经分析过LifecycleBase类的start()方法具体源码,因为start()方法中会调用子类的startInternal()方法,所以可以直接查看StandardServer类的startInternal()方法。

    @Override
    protected void startInternal() throws LifecycleException {
    
        fireLifecycleEvent(CONFIGURE_START_EVENT, null);
        setState(LifecycleState.STARTING);
    
        globalNamingResources.start();
        
        // Start our defined Services
        synchronized (servicesLock) {
            for (int i = 0; i < services.length; i++) {
                services[i].start();
            }
        }
    }
    

    可以看到思路非常简单

    • 触发某个事件(针对自己内部所有监听器)
    • 更改自己组件状态
    • 调用子组件的start()方法,包括globalNamingResourcesStandardService

    至于这些子组件什么时候设置到本类中的,读者可以自行发现。

    我们可以继续往下再看一点,既然调用了StandardServicestart()方法,查看StandardService类的定义。

    public class StandardService extends LifecycleMBeanBase implements Service
    

    类似StandardServer,那么直接查看其startInternal()方法。

        @Override
    protected void startInternal() throws LifecycleException {
    
        if(log.isInfoEnabled())
            log.info(sm.getString("standardService.start.name", this.name));
        setState(LifecycleState.STARTING);
    
        // Start our defined Container first
        if (container != null) {
            synchronized (container) {
                container.start();
            }
        }
    
        synchronized (executors) {
            for (Executor executor: executors) {
                executor.start();
            }
        }
    
        // Start our defined Connectors second
        synchronized (connectorsLock) {
            for (Connector connector: connectors) {
                try {
                    // If it has already failed, don't try and start it
                    if (connector.getState() != LifecycleState.FAILED) {
                        connector.start();
                    }
                } catch (Exception e) {
                    log.error(sm.getString(
                            "standardService.connector.startFailed",
                            connector), e);
                }
            }
        }
    }
    

    虽然代码看起来很多,但是按照上面的思路来看的话,还是那几步。

    • 更改当前组件状态
    • 调用自己子组件的start()方法包含container,connector

    看到这里我们就不继续往下看了,因为之前启动的文章都已经分析过了,是不是觉得看到这里对启动的流程理解又上了一层。其实自己看看每个组件的startInternal()方法都是在启动自己的子组件,而组件的子组件可以从哪里找到呢?可以看看Digster那篇文章,疑惑看看server.xml也许会有恍然大悟的感觉,至于具体代码去哪里找,读者可以自行挖掘。

    写到这里只能感慨Tomcat设计者设计的精巧,代码的简洁,简直完美!

  • 相关阅读:
    solr集群
    mybatis的逆向工程
    使用secureCRT上传下载
    Linux vim基本的使用方法
    非web下的PowerMockito单元测试
    打印日志
    集群
    免安装版tomcat安装成服务
    apache安装zip包安装(非exe)
    Java 性能优化(一)
  • 原文地址:https://www.cnblogs.com/coldridgeValley/p/5816417.html
Copyright © 2011-2022 走看看