zoukankan      html  css  js  c++  java
  • 【杂谈】Tomcat 之 Lifecycle接口

    前言

      此篇随笔记录《How Tomcat works》中关于Lifecycle接口的相关总结

    Lifecycle接口的主要目的

    核心:统一。

    已知Tomcat的卡特琳娜(Catalina)由许多组件构成。当Catalina启动的时候,这些组件也要跟着一起启动,并且当Catalina关闭的时候,这些组件也要同时关闭,并且要进行必要的清理操作,释放资源。例如,当容器关闭的时候,需要调用已加载的servlet对象的destroy方法,session对象也要持久化到secondary storage(二级存储,通常指的就是硬盘)。这就要求所有Component有一致的方法,可以统一处理。

    如果没有统一会怎么样?

    其实也不会怎么样,就是编程起来就比较麻烦。比如有的对象初始化方法叫initiate,有的又叫init。用都可以用,就是不太好用,即你要记住这个对象的初始化方法到底叫什么。而统一之后呢,可以放到一个List中,遍历调用。这不就方便多了嘛。

    Lifecycle的事件与监听

    Lifecycle,翻译过来就是“生命周期”。那生命周期变化,从一个生命周期进入另一个生命周期,自然就会有相应的事件来表示。比如,人从幼儿长大成人,这是一个事件“成长”,而从中年步入老年,又是另外一个事件“衰老”。那么既然有事件的触发,那就会有事件的监听处理,常见的有两大种。

    Lifecycle事件监听器原理

    其实就是观察者模式了,熟悉的人就不用看了。关联的类清单如下:

    • LifecycleEvent(事件对象)
    • Lifecycle 接口
    • LifecycleListener 接口
    • LifecycleBase => 用于存储并触发监听器,《How Tomcat works》里是比较旧的,对应的是LifecycleSupport类

    (1)LifecycleEvent

    LifecycleEvent继承于EventObject,EventObject是JDK提供的,它只有一个字段,即Object类型的source,用于表示事件的产生者。

    public class EventObject implements java.io.Serializable {
    
        private static final long serialVersionUID = 5516075349620653480L;
    
        /**
         * The object on which the Event initially occurred.
         */
        protected transient Object  source;
    
        public EventObject(Object source) {
            if (source == null)
                throw new IllegalArgumentException("null source");
    
            this.source = source;
        }
    
        public Object getSource() {
            return source;
        }
    
        public String toString() {
            return getClass().getName() + "[source=" + source + "]";
        }
    }
    public final class LifecycleEvent extends EventObject {
    
        private static final long serialVersionUID = 1L;
    
    
        /**
         * 
         *
         * @param lifecycle 指明当前事件在哪个lifecycle组件上产生
         * @param type Event type 事件类型
         * @param data Event data 额外的数据
         */
        public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
            //把lifecycle赋给source
            super(lifecycle);
            this.type = type;
            this.data = data;
        }
    
    
        /**
         *  与此事件关联的事件数据
         */
        private final Object data;
    
    
        /**
         * 事件类型
         */
        private final String type;
    
    
        public Object getData() {
            return data;
        }
    
        public Lifecycle getLifecycle() {
            return (Lifecycle) getSource();
        }
    
        public String getType() {
            return this.type;
        }
    }

    (2)Lifecycle接口

    public interface Lifecycle { 
    
        //统一的事件类型
        public static final String BEFORE_INIT_EVENT = "before_init";
        public static final String AFTER_INIT_EVENT = "after_init";
        public static final String START_EVENT = "start";
        public static final String BEFORE_START_EVENT = "before_start";
        public static final String AFTER_START_EVENT = "after_start";
        public static final String STOP_EVENT = "stop";
        public static final String BEFORE_STOP_EVENT = "before_stop";
        public static final String AFTER_STOP_EVENT = "after_stop";
        public static final String AFTER_DESTROY_EVENT = "after_destroy";
        public static final String BEFORE_DESTROY_EVENT = "before_destroy";
        public static final String PERIODIC_EVENT = "periodic";
        public static final String CONFIGURE_START_EVENT = "configure_start";
        public static final String CONFIGURE_STOP_EVENT = "configure_stop";
    
        //lifecycle表示的是一个组件,故可以在组件上添加监听器
        public void addLifecycleListener(LifecycleListener listener);
    
        //获取注册在此组件上的监听器
        public LifecycleListener[] findLifecycleListeners();
    
        //移除某个监听器
        public void removeLifecycleListener(LifecycleListener listener);
    
        //统一的生命周期方法
        public void init() throws LifecycleException;
    
        public void start() throws LifecycleException;
    
        public void stop() throws LifecycleException;
    
        public void destroy() throws LifecycleException;
    
        //获取组件状态
        public LifecycleState getState();
    
        public String getStateName();
    
        public interface SingleUse {
        }
    }

    (3)LifecycleListener接口

    public interface LifecycleListener {
    
        //接收事件对象作为参数
        //在方法体内,根据事件类型做自定义的响应
        public void lifecycleEvent(LifecycleEvent event);
    
    }

    (4)LifecycleBase 抽象类

    一般组件都以此为父类。主要看存监听器的List和fireLifecycleEvent方法。以下把大部分代码省略了,感兴趣的可自行翻阅源码。

    public abstract class LifecycleBase implements Lifecycle {
    
        private static final Log log = LogFactory.getLog(LifecycleBase.class);
    
        private static final StringManager sm = StringManager.getManager(LifecycleBase.class);
    
        //用于存储注册在此组件上的监听器
        private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();
    
        //组件状态
        private volatile LifecycleState state = LifecycleState.NEW;
    
    
        private boolean throwOnFailure = true;
    
        public boolean getThrowOnFailure() {
            return throwOnFailure;
        }
    
        public void setThrowOnFailure(boolean throwOnFailure) {
            this.throwOnFailure = throwOnFailure;
        }
    
    
        @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);
        }
    
    
        //触发事件,告知所有监听器。
        protected void fireLifecycleEvent(String type, Object data) {
            LifecycleEvent event = new LifecycleEvent(this, type, data);
            for (LifecycleListener listener : lifecycleListeners) {
                listener.lifecycleEvent(event);
            }
        }
    
    
        @Override
        public final synchronized void init() throws LifecycleException {
            //...省略
        }
    
        protected abstract void initInternal() throws LifecycleException;
    
    
        @Override
        public final synchronized void start() throws LifecycleException {
            //...省略
        }
    
        protected abstract void startInternal() throws LifecycleException;
    
    
        @Override
        public final synchronized void stop() throws LifecycleException {
            //...省略
        }
    
    
        protected abstract void stopInternal() throws LifecycleException;
    
    
        @Override
        public final synchronized void destroy() throws LifecycleException {
            //...省略
        }
    
    
        protected abstract void destroyInternal() throws LifecycleException;
    
        @Override
        public LifecycleState getState() {
            return state;
        }
    
    
        @Override
        public String getStateName() {
            return getState().toString();
        }
    
        protected synchronized void setState(LifecycleState state) throws LifecycleException {
            setStateInternal(state, null, true);
        }
    
        protected synchronized void setState(LifecycleState state, Object data)
                throws LifecycleException {
            setStateInternal(state, data, true);
        }
    
    
        private synchronized void setStateInternal(LifecycleState state, Object data, boolean check)
                throws LifecycleException {
    
            //...省略
        }
    
    
        private void invalidTransition(String type) throws LifecycleException {
            //...省略
        }
    
    
        private void handleSubClassException(Throwable t, String key, Object... args) throws LifecycleException {
            //...省略
        }
    }

     

  • 相关阅读:
    自增主键强制修改
    网页速度优化
    JS 获取字符串长度, 区别中英文
    SQL时间相关 SQL日期,时间比较
    关于document.cookie的使用
    php文件头部空白影响CSS布局 2
    FlvPlayer 播放器代码
    JAVA——继承、多态、重载和重写转
    JS星级评分,带提示(转)
    web 启动 本地应用程序 Activity
  • 原文地址:https://www.cnblogs.com/longfurcat/p/10639297.html
Copyright © 2011-2022 走看看