• Tomcat8源码笔记(一)Lifecycle接口


    第一次阅读Tomcat8源码,就以Lifecycle作为笔记阅读的开篇吧,一千个读者就有一千个哈姆雷特,每个人都Tomcat的理解都不同,如果不记录一次Tomcat源码可能忘了就忘了. 断断DEBUG了几天,决定从Lifecycle开始记录.

     

    LifeCycle接口定义如下:

    个人理解:Lifecycle接口定义了生命周期描述的字符常量,初始化之前、初始化之后、启动、启动之前、启动之后、停止、停止之前、停止之后、销毁之前、销毁之后等等;定义了生命周期监听器的三个方法,添加监听器、获得组件上监听器以及移除监听器;定义了组件的四个方法,初始化、启动、停止、销毁;定义了获取当前组件生命状态、生命状态名称;

    image

    LifecycleState是枚举,描述着声明周期的状态

    image

     

    Lifecycle接口实现类中比较重要LifecycleBase,以及LifecycleSupport类.

    三者之间关系大概这样:LifecycleBase继承Lifecycle,且持有LifecycleSupport属性,LifecycleSupport也持有Lifecycle属性.image

     

    LifecycleBase抽象类

    LifecycleBase持有LifecycleSupport实例lifecycle,而lifecycle本身持有的是Lifecycle类型,也就意味着如果有一个LifecycleBase的实例A,那A的lifecycle属性也持有A,我有你,你也有我. LifecycleBase实现了Lifecycle的监听器的方法,全部是对LifecycleSupport进行操作;LifecycleBase包括实现类默认创建的时候状态state都是LifecycleState.NEW.

    image

     

    LifecycleSupport类

    LifecycleSupport持有Lifecycle实例,以及一个LifecycleListener集合listeners,所有添加、查找所有监听器、移除监听器、触发监听事件都是通过listeners来完成.

    image

    Tomcat的Lifecycle,如果要说设计模式,我觉得 观察者模式应该合适些.  观察者模式又被称为源-收听者模式(Listener),百度百科这么介绍该设计模式 : 一个目标物件管理所有依赖于他的观察者物件,并且在他本身状态发生改变时主动发出通知,通常用于事件处理系统。所以,这是我觉得Lifecycle可以称为观察者模式的原因,下面是Tomcat中StandardServer启动的过程,fireLifecycleEvent,Server主动去通知它的LifecycleListener,执行相应处理逻辑。

    image

    简单写个类似的例子,描述下我认为的观察者模式,一个考试Exam,一个闹钟类RingBell,闹钟一直在走,当闹钟到11.25分就去通知考试开始,中间过程省略一直到收卷结束。

    Exam考试类

    public class Exam implements Lifecycle {
        public void init()  { System.out.println("监考老师分发考卷"); }
        public void start() { System.out.println("监考老师: 考试开始,大家可以做题了"); }
        public void stop() { System.out.println("监考老师:时间到,停止答题"); }
        public void destroy(){ System.out.println("监考老师收完卷子走人"); }
    
        private LifecycleSupport lifecycle=new LifecycleSupport(this);
        public void addLifecycleListener(final LifecycleListener listener) {
            lifecycle.addLifecycleListener(listener);
        }
    
        public LifecycleListener[] findLifecycleListeners() {
            return lifecycle.findLifecycleListeners();
        }
    
        public void removeLifecycleListener(final LifecycleListener listener) {
            lifecycle.removeLifecycleListener(listener);
        }
        public LifecycleState getState() {
            return null;
        }
        public String getStateName() {
            return null;
        }
    }

     

    RingBell类

    public class RingBell implements Lifecycle {
    
        private boolean flag=true;
        public void setFlag(final boolean flag) {
            this.flag = flag;
        }
    
        private LifecycleSupport lifecycle=new LifecycleSupport(this);
        public void addLifecycleListener(final LifecycleListener listener) {
            lifecycle.addLifecycleListener(listener);
        }
        public LifecycleListener[] findLifecycleListeners() {
            return lifecycle.findLifecycleListeners();
        }
        public void removeLifecycleListener(final LifecycleListener listener) {lifecycle.removeLifecycleListener(listener); }
        public void start() throws LifecycleException { }
        public void stop() throws LifecycleException { }
        public void destroy() throws LifecycleException {}
        public LifecycleState getState() { return null; }
        public String getStateName() { return null; }
    
        public void init() throws LifecycleException {
            System.out.println("时钟慢慢走动.....");
            while(flag){
                Date now = new Date();
                System.out.println(new SimpleDateFormat("hh:mm:ss").format(now));
                if(now.getHours()==11 && now.getMinutes()== 25 && now.getSeconds()==0){
                    lifecycle.fireLifecycleEvent(Lifecycle.AFTER_INIT_EVENT,null);
                }else if(now.getHours()==11 && now.getMinutes()== 25  && now.getSeconds()== 2){
                    lifecycle.fireLifecycleEvent(Lifecycle.START_EVENT,null);
                }else if(now.getHours()==11 && now.getMinutes()== 25 && now.getSeconds()==4){
                    lifecycle.fireLifecycleEvent(Lifecycle.STOP_EVENT,null);
                }else if(now.getHours()==11 && now.getMinutes()== 25  && now.getSeconds()== 6){
                    lifecycle.fireLifecycleEvent(Lifecycle.AFTER_DESTROY_EVENT,null);
                }else if(now.getHours()==11 && now.getMinutes()== 25  && now.getSeconds()== 8){
                    lifecycle.fireLifecycleEvent(Lifecycle.AFTER_DESTROY_EVENT,null);
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("谁把时钟关了");
        }
    
    }

     

    ExamListener

    public class ExamListener implements LifecycleListener {
    
        private Exam exam;
        public ExamListener(final Exam exam) {
            this.exam = exam;
        }
        public void lifecycleEvent(final LifecycleEvent event) {
            if(event.getType().equals(Lifecycle.AFTER_INIT_EVENT)){
                exam.init();
            }else if(event.getType().equals(Lifecycle.START_EVENT)){
                exam.start();
            }else if(event.getType().equals(Lifecycle.STOP_EVENT)){
                exam.stop();
            }else if(event.getType().equals(Lifecycle.AFTER_DESTROY_EVENT)){
                exam.destroy();
                RingBell ringBell= (RingBell) event.getLifecycle();
                ringBell.setFlag(false);
            }
        }
    }

    测试方法:

     public static void main(String[] args) throws LifecycleException {
            Exam exam = new Exam();
            RingBell ringBell=new RingBell();
            ringBell.addLifecycleListener(new ExamListener(exam));
            ringBell.init();
        }

     

    解释说明: RingBell作为被观察对象,观察对象就是ExamListener, RingBell持有观察对象ExamListener,当RingBell状态改变(当前时间改变),就去通知观察者们,观察者们就触发事件,开始考试啊、结束考试等等;

    这里的观察者不是具象的观察者对象,而是监听器类型LifecycleListener,通过监听器来使Exam做出响应处理,事件驱动机制。测试效果如下:

    注意 RingBell对象 不合适 直接持有Exam的引用, 耦合性太高,假如再来一个观察者监考老师,监考老师需要考试期间来巡查,那我们只需要添加一个LifecycleListener实现类即可,不需要让RingBell持有这个监考老师监听器。

    image

     

    Lifecycle代表了Tomcat的组件的生命周期,定义过init、start、stop、destroy等四个重要的方法。而Tomcat的重要组件全部都实现了LifecycleBase接口,继承了LifecycleBase接口,下图是利用IDEA画出来的继承关系:

    image

     

    LifecycleBase抽象类采用了模板设计模式,听说过采用了模板设计模式的有Arrays.sort方法、Servlet的service方法,模板设计模式的好处就是 统一按照模板执行,共性的基础上个性的地方,再各自处理。

     

    LifecycleBase的init模板方法:

    state默认为LifecycleState.NEW,所以第一步的目的是为了防止多次调用init方法,Tomcat组件基本上初始化一次就够了。

    init模板共性的地方就是设置当前组件状态,LifecycleState.INITIALIZING以及LifecycleState.INITIALIZED,个性之处在于initInternal,不同组件实现逻辑就是这里体现的。

    而共性的设置组件状态的目的呢?接着往下看。

    image

     

    设置组件状态,check为true会再次校验组件状态,一般check都为false.  更新组件的状态,之后就是观察者模式的应用,主动通知组件上左右的监听器LifecycleListener,触发相应的事件。image

     

    通过上面两段代码分析,一个组件init初始化大致过程:组件上所有监听器,如果有的话触发LifecycleState.INITIALIZING,也就是before_init,  接着initInternal,就是组件自己会重写的方法,接着触发组件上监听器的LifecycleState.INITIALIZED,也就是after_init类型事件!

     

     

    LifecycleBase的start模板方法

    首先检查组件状态,如果已经处于启动相关状态,before_start/after_start/start状态的话,打印日志并且不再启动;

    组件如果还没初始化呢,那赶紧初始化;组件初始化、启动失败了,赶紧停止组件;到这里,如果组件不是初始化完成或者停止的状态,那就有问题了,启动中?启动了? 正要启动组件,你启动好了,抛出异常;

    上述检查都没问题,那设置状态LifecycleState.STARTING_PREP,也就是before_start,目的不用多说了吧,启动组件上监听器,触发before_start的事件啊,接着才是各个组件个性的startInternal,启动完成没有问题,那就设置状态LifecycleState.STARTED,也就是after_start,目的同样启动组件监听器触发after_start事件。

    image

     

    剩下两个stop 、destory模板方法,不用我说肯定是类似的,这里就不多此一举了,毕竟我们连Tomcat启动干了啥都不知道,相比于分析停止、摧毁的模板方法,还是留时间分析Tomcat的启动吧。

     

    总结

    感觉自己这样一整理舒畅多了,见识两种设计模式,也请求了Tomcat的组件的初始化、启动流程要干啥,从哪里分析了,核心就是Lifecycle接口以及LifecycleBase以及LifecycleListener,接下来,只需要关注组件上有哪些监听器、初始化initInternal、启动startInternal过程干了啥。

     

  • 相关阅读:
    Air-WIFI使用方法
    libeasy代码学习:一次简单的TCP请求处理流程
    log_pipe日志收集分析系统介绍
    asp.net 项目在 IE 11 下出现 “__doPostBack”未定义 的解决办法
    用命令行实现“一键休眠”
    C#几个经常用到的字符串的截取
    MYSQL存储过程怎么写
    如何用myeclipse和eclipse搭建安卓开发环境
    C#随机生成不重复字符串
    Inno setup 简单打包教程
  • 原文地址:https://www.cnblogs.com/lvbinbin2yujie/p/10658384.html
Copyright © 2020-2023  润新知