zoukankan      html  css  js  c++  java
  • 【深入剖析Tomcat笔记】第六篇 Tomcat Lifecycle

    简述

    上一篇中介绍了Tomcat四大容器,Enginee、Host、Context和Wrapper以及如何通过TaskPipeline对四大容器进行功能性扩展。在 第五篇 Tomcat Container和PipeliningTasks 中我们介绍了如何通过Pipeline Task去为Enginee添加一些共用的方法,但这样还存在一些问题,我们很难对Container实例进行管理。Composite模式的一个明显的弊端就是存在大量的子容器,难以进行管理。为了解决这个问题,本篇将以四大容器为核心介绍Tomcat的生命周期。

    Event

    在之前的程序中,我们对容器进行管理是通过代码来实现的。
    例如

    ...
    context.start();
    context.execute();
    context.end();
    ...

    Tomcat中非常核心的一个特性是向用户提供一个容器环境实现多线程,且用户透明(用户不需要关心多线程实现)。但用户在某些高级特性时候需要介入容器的管理,此时采用代码形式进行管理不足以实现这部分功能,用户若需要介入,则需要改动tomcat源码。
    Event相当于Tomcat暴露给用户的一个接口去实现这部分功能,用户在需要感知Tomcat容器时,仅仅需要实现对应的event即可。

    相信熟悉Spring的小伙伴们已经对于Event已经非常熟悉了,在此简单介绍一下Event。

    Event是运行状态和暴露资源的封装

    JDK1.1中提供了EventObject对象实现事件驱动,在没有EventObject的情况下我们实现对象运行状态管理(例如:运行,停止、自定义….),一种方式是硬编码,这种方式无法由外部模块控制,另外一种方式是轮询,这种方式外部模块不需要感知内部状态,明显的缺点是消耗大量计算资源。EventObject很好的解决了这个问题。
    以下是JDK对于EventObject介绍

    /**
     * <p>
     * The root class from which all event state objects shall be derived.
     * <p>
     * All Events are constructed with a reference to the object, the "source",
     * that is logically deemed to be the object upon which the Event in question
     * initially occurred upon.
     *
     * @since JDK1.1
     */
    public class EventObject implements java.io.Serializable {
        protected transient Object  source;
    
        //构造方法
        public EventObject(Object source) {
            if (source == null)
                throw new IllegalArgumentException("null source");
    
            this.source = source;
        }
    
        //Get
        public Object getSource() {
            return source;
        }
    }

    不难理解,Event核心在于对于资源的暴露。在EventObject对应的核心资源是发布这个事件的对象,因此我们看到实际是对发布对象的持有 。
    进一步考虑,我们对于Tomcat的Event需求是什么?回到最初的问题,我们主要需要对Tomcat进行管理,Tomcat对于容器运行阶段做了一个抽象叫做Lifecycle(生命周期)。生命周期其实就是对于常用执行状态的抽象,下一节会给大家介绍。因此我们对于Tomcat生命周期LifecycleEvent设计如下

    public final class LifecycleEvent extends EventObject {
    
        private final Lifecycle lifecycle;
        //生命周期具体阶段参数
        private final String type;
        //可扩展资源
        private final Object data;
    
        public LifecycleEvent(Object source, Lifecycle lifecycle, String type) {
            this(lifecycle, type, null);
        }
    
        public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
            super(lifecycle);
            this.lifecycle = lifecycle;
            this.type = type;
            this.data = data;
        }
    
    
        public Lifecycle getLifecycle() {
            return lifecycle;
        }
    
        public String getType() {
            return type;
        }
    
        public Object getData() {
            return data;
        }
    }

    Lifecycle

    上一节中,我们了解到Tomcat对于容器的运行状态做了抽象,抽象的内容被叫做Lifecycle
    实际上Tomcat 对于容器运行状态抽象为六个状态,如示例所示。并且Lifecycle对象允许LifecycleListener,LifecycleListener下一节会说明。
    对于需要对状态监测的对象,需要实现Lifecycle接口

    public interface Lifecycle {
    
    
        String START_EVENT = "start";
    
        String BEFORE_START_EVENT = "before_start";
    
        String AFTER_START_EVENT = "after_start";
    
        String STOP_EVENT = "stop";
    
        String BEFORE_STOP_EVENT  = "before_stop";
    
        String AFTER_STOP_EVENT = "after_stop";
    
        //增加LifecycleListener
        void addLifecycleListener(LifecycleListener listener);
        //获取全部LifecycleListener
        LifecycleListener[] findLifecycleListeners();
        //移除对应LifecycleListener
        void removeLifecycleListener(LifecycleListener listener);
        //Lifecycle对象启动
        void start() throws LifecycleException;
        //Lifecycle对象停止
        void stop() throws LifecycleException;
    }

    LifecycleListener

    LifecycleListener是对Lifecycle的接口的抽象
    核心方法lifecycleEvent通过LifecycleEvent进行容器声明周期管理

    public interface LifecycleListener {
    
        void lifecycleEvent(LifecycleEvent event);
    }

    在此示例SimpleContextLifecycleListener

    public class SimpleContextLifecycleListener implements LifecycleListener {
    
      public void lifecycleEvent(LifecycleEvent event) {
        Lifecycle lifecycle = event.getLifecycle();
        System.out.println("SimpleContextLifecycleListener's event " +
          event.getType().toString());
        //声明周期控制 启动阶段
        if (Lifecycle.START_EVENT.equals(event.getType())) {
          System.out.println("Starting context.");
        }
        //声明周期控制 停止阶段
        else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
          System.out.println("Stopping context.");
        }
      }
    }

    实际上,基于Lifecycle的6个阶段,我们可以进行各个阶段的控制。
    这三者的结构如下。

    Lifecycle

    DEMO实现

    由于每种Container都需要实现Lifecycle接口,对于这部分抽象对象LifecycleSupport

    public final class LifecycleSupport {
    
        private  Lifecycle lifecycle;
    
        private LifecycleListener listeners[] = new LifecycleListener[0];
    
        public LifecycleSupport(Lifecycle lifecycle) {
            super();
            this.lifecycle = lifecycle;
        }
    
        public void addLiffecycleListener(LifecycleListener listener) {
            synchronized (listeners) {
    
                LifecycleListener results[] = new LifecycleListener[listeners.length + 1];
                for (int i = 0; i < listeners.length; i++) {
                    results[i] = listeners[i];
                }
                results[listeners.length] = listener;
                listeners = results;
            }
        }
    
        public LifecycleListener[] findLifecycleListeners() {
            return listeners;
        }
    
        public void fireLifecycleEvent(String type, Object data) {
            LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
            LifecycleListener interested[] = null;
    
            synchronized (listeners) {
                interested = (LifecycleListener[]) listeners.clone();
            }
    
            for (int i = 0; i < interested.length; i++) {
                interested[i].lifecycleEvent(event);
            }
    
        }
    
        public void removeLifecycleListener(LifecycleListener listener) {
            synchronized (listeners) {
                int n = -1;
                for (int i = 0; i < listeners.length; i++) {
                    if(listeners[i] == listener) {
                        n = i;
                        break;
                    }
                }
                if(n < 0)
                    return;
    
                LifecycleListener results[] = new LifecycleListener[listeners.length - 1];
    
                int j = 0;
                for (int i = 0; i < listeners.length; i++) {
                    if(i != n) {
                        results[j++ ] = listeners[i];
                    }
                }
                listeners = results;
            }
        }
    }

    这里只演示之前写的SimpleContext,其余容器类似

    public class SimpleContext extends ContainerBase implements Context, Lifecycle {
    
        private LifecycleSupport lifecycleSupport = new LifecycleSupport(this);
    
        @Override
        public void addLifecycleListener(LifecycleListener listener) {
            lifecycleSupport.addLiffecycleListener(listener);
        }
    
        @Override
        public LifecycleListener[] findLifecycleListeners() {
            return lifecycleSupport.findLifecycleListeners();
        }
    
        @Override
        public void removeLifecycleListener(LifecycleListener listener) {
            lifecycleSupport.removeLifecycleListener(listener);
        }
    
        @Override
        public void start() throws LifecycleException {
    
            lifecycleSupport.fireLifecycleEvent(Lifecycle.BEFORE_START_EVENT, null);
    
    
            lifecycleSupport.fireLifecycleEvent(Lifecycle.START_EVENT, null);
            Container[] lifeChildren = findChildren();
            for (Container child :
                    lifeChildren) {
                ((Lifecycle) child).start();
            }
    
            lifecycleSupport.fireLifecycleEvent(Lifecycle.AFTER_START_EVENT, null);
    
        }
    
        @Override
        public void stop() throws LifecycleException {
            lifecycleSupport.fireLifecycleEvent(Lifecycle.BEFORE_START_EVENT, null);
    
            lifecycleSupport.fireLifecycleEvent(Lifecycle.STOP_EVENT, null);
            Container[] lifeChildren = findChildren();
            for (Container child :
                    lifeChildren) {
                ((Lifecycle) child).stop();
            }
    
            lifecycleSupport.fireLifecycleEvent(Lifecycle.AFTER_STOP_EVENT, null);
        }
    }
  • 相关阅读:
    【Windows核心编程】重载类成员函数new / new[] / delete / delete[]
    【数据结构和算法】 O(1)时间取得栈中的最大 / 最小元素值
    路由器与交换机做链路聚合
    怎么样判断两个IP地址是否在同一个网段
    sqlite常用的命令-增删改查
    5G时代的智慧灯杆需要哪种网关?
    什么是边缘计算网关?
    5G/4G工业智能网关在工业物联网的必要性
    基于5G/4G网关的冷冻设备远程监测及故障预警系统
    工业5G网关配置POE技术的优势
  • 原文地址:https://www.cnblogs.com/cunchen/p/9464102.html
Copyright © 2011-2022 走看看