• Jetty


    1. 描述

    Container提供管理bean的能力。

    基于Jetty-9.4.8.v20171121。

    1.1 API

    public interface Container
    {
        // 增加一个bean,如果bean是一个Container.Listener则隐含调用addEventListener(Container.Listener)方法
        // Container.Listener只关心两个事件:(1)增加bean(2)删除bean
        public boolean addBean(Object o);
    
        // 返回该Container里面所有的bean
        public Collection<Object> getBeans();
    
        // 返回指定类型(包括子类)的bean
        public <T> Collection<T> getBeans(Class<T> clazz);
    
        // 返回指定类型(包括子类)的第一个bean,如果不存在则返回null
        public <T> T getBean(Class<T> clazz);
    
        // 删除指定的bean,如果bean是一个Container.Listener,隐含调用removeEventListener(Container.Listener)
        public boolean removeBean(Object o);
        
        // 增加一个Listener
        public void addEventListener(Listener listener);
        
        // 删除一个Listener
        public void removeEventListener(Listener listener);
    
        // 未托管一个bean(必须已经存在在Container里面),所以该bean不应该启动,停止或销毁
        void unmanage(Object bean);
    
        // 托管一个bean(必须已经存在在Container里面),所以该bean已启动,已停止或销毁
        void manage(Object bean);
    
    
        // 检测该Container是否托管一个bean
        boolean isManaged(Object bean);
    
        // 增加一个bean,并且明确是否托管(即是否管理该bean的生命周期)
        // 如果已经增加返回true,如果已经存在返回false 
        boolean addBean(Object o, boolean managed);
    
        // Container事件的监听器
        // 如果一个增加的bean实现该接口将会收到该Container的事件
        public interface Listener
        {
            void beanAdded(Container parent,Object child);
            void beanRemoved(Container parent,Object child);
        }
        
        /**
         * Inherited Listener.
         * If an added bean implements this interface, then it will 
         * be added to all contained beans that are themselves Containers
    * 如果增加的bean实现该接口,则将该bean增加到当前Container里面所有bean类型为Container里面。 */ public interface InheritedListener extends Listener { } /** * @param clazz the class of the beans * @return the list of beans of the given class from the entire managed hierarchy * @param <T> the Bean type */ public <T> Collection<T> getContainedBeans(Class<T> clazz); }  

    从API可以看出Container主要维护bean并且监听bean的增加和删除事件。

    1.2 类图

    从类图可以看出,Container与LifeCycle接口很类似,都是很多组件的基本特征,其默认实现是ContainerLifeCycle。

    2. ContainerLifeCycle

    1.2类图可以看出ContainerLifeCycle不仅是Container的默认实现,而且也是很多组件(Connector,Handler等)默认实现的父类。

    2.1 类图

    ContainerLifeCycle自然要实现Container接口; 

    ContainerLifeCycle继承AbstractLifeCycle,而AbstractLifeCycle里面实现了LifeCycle的模板启停方法start和stop;

    继承AbstractLifeCycle的子类只需要实现AbstractLifeCycle中增加的doStart和doStop实现子类具体的启动和停止,具体请参考【Jetty - LifeCycle源码分析】

    ContainerLifeCycle.Bean:内部类,表示管理的Bean对象。

    ContainerLifeCycle.Managed:内部类,被管理的Bean有几种类型:POJO,MANAGED,UNMANAGED,AUTO。

    2.2 doStart和doStop

      启动主要分为如下两个步骤:

     (1)设置标志位_doStart = true;

     (2)启动具有生命周期的bean(a)如果托管bean并且未运行的,则启动(b)如果是自动bean并且运行中,则设置为未托管;未运行的,则设置为托管,并且启动; 

        // 以添加的顺序启动托管的bean
        @Override
        protected void doStart() throws Exception
        {
            if (_destroyed)
                throw new IllegalStateException("Destroyed container cannot be restarted");
    
            // 标示已经启动,addBean可以启动其他的bean
            _doStarted = true;
    
            // 启动托管和自动beans
            for (Bean b : _beans) // 遍历所有bean
            {
                if (b._bean instanceof LifeCycle)
                {
                    LifeCycle l = (LifeCycle)b._bean;
                    switch(b._managed)
                    {
                        case MANAGED: // 如果是托管bean,并且未运行,则启动
                            if (!l.isRunning())
                                start(l);
                            break;
                        case AUTO: // 如果是自动bean
                            if (l.isRunning()) // 如果已经运行了,则设置为未托管
                                unmanage(b);
                            else // 如果未运行,设置为托管,并且启动
                            {
                                manage(b); 
                                start(l);
                            }
                            break;
                    }
                }
            }
            // 此处调用父类的doStart方法,就是AbstractLifeCycle的doStart方法,其实是个空实现
            super.doStart();
        }  

    停止主要分为两个步骤:

    (1)设置标志位;

    (2)逆序停止具有生命周期的托管bean,为什么逆序?主要与启动顺序比较,防止bean之间有关联出现错误,类似资源释放。

        // 以添加的逆序停止具有生命周期的托管bean
        @Override
        protected void doStop() throws Exception
        {  
            _doStarted = false; // 设置停止状态位
            super.doStop(); // 调用AbstractLifeCycle的doStop方法,其实是个空方法
            List<Bean> reverse = new ArrayList<>(_beans);
            Collections.reverse(reverse); // 逆序
            for (Bean b : reverse) 
            {   // 具有生命周期并且托管的bean
                if (b._managed==Managed.MANAGED && b._bean instanceof LifeCycle)
                {
                    LifeCycle l = (LifeCycle)b._bean;
                    stop(l);
                }
            }
        }  

    2.3 addBean

    // o:bean,managed:bean类型
    // 注意基本原则:在ContainerLifeCycle类里面有两个字段_beans和_listener,如果添加的bean也是Container.Listener类型,则需要在_listener里面也增加一个
    public boolean addBean(Object o, Managed managed)
        {
            if (o==null || contains(o)) // 如果bean为null或者已经存在
                return false;
    
            Bean new_bean = new Bean(o); // 包装为Bean对象
    
            // 如果bean是Container.Listener
            if (o instanceof Container.Listener)
                addEventListener((Container.Listener)o);
    
            // 添加bean
            _beans.add(new_bean);
    
            // 通知所有_listeners,有新bean添加的事件
            for (Container.Listener l:_listeners)
                l.beanAdded(this,o);
    
            try
            {
                switch (managed)
                {
                    case UNMANAGED:
                        unmanage(new_bean);
                        break;
    
                    case MANAGED:
                        manage(new_bean);
                        // 如果ContainerLifeCycle在启动中,即调用doStart还没有退出
                        if (isStarting() && _doStarted) 
                        {  // 此处o是一个任意类型且是个public方法,此处直接转为LifeCycle是否有问题?
                            LifeCycle l = (LifeCycle)o;
                            // 为什么有这样的判断?
                            // doStart的过程(1)设置状态位(2)以bean添加的顺序启动具有生命周期的bean,如果此时调用了addBean有可能同步的问题,导致新添加的bean没有通过doStart启动,所以需要在此处判断如果未启动,则启动一下
                            if (!l.isRunning()) 
                                start(l);
                        }
                        break;
    
                    case AUTO:
                        if (o instanceof LifeCycle)
                        {
                            LifeCycle l = (LifeCycle)o;
                            if (isStarting()) // 如果ContainerLifeCycle启动中
                            {
                                if (l.isRunning()) // 如果bean运行中,则设置为未托管,不需要ContainerLifeCycle管理启动
                                    unmanage(new_bean);
                                else if (_doStarted) // 如果bean未运行,并且ContainerLifeCyle启动中,则设置为托管bean并且启动之
                                {
                                    manage(new_bean);
                                    start(l);
                                }
                                else
                                    new_bean._managed=Managed.AUTO;      
                            }
                            else if (isStarted()) // 如果ContainerLifeCycle已经启动
                                unmanage(new_bean);
                            else // ContainerLifeCycle未启动
                                new_bean._managed=Managed.AUTO;
                        }
                        else
                            new_bean._managed=Managed.POJO;
                        break;
    
                    case POJO:
                        new_bean._managed=Managed.POJO;
                }
            }
            catch (RuntimeException | Error e)
            {
                throw e;
            }
            catch (Exception e)
            {
                throw new RuntimeException(e);
            }
    
            if (LOG.isDebugEnabled())
                LOG.debug("{} added {}",this,new_bean);
    
            return true;
        }
    
    // 删除bean
    private boolean remove(Bean bean)
        {
            if (_beans.remove(bean))
            {
                boolean wasManaged = bean.isManaged(); // bean是否是托管类型
                
                unmanage(bean); // 设置bean为未托管类型
    
                for (Container.Listener l:_listeners) // 通知监听器
                    l.beanRemoved(this,bean._bean);
                // 如果被remove的bean是Listener,需要调用removeEventListener
                if (bean._bean instanceof Container.Listener) 
                    removeEventListener((Container.Listener)bean._bean);
    
                // 如果是具有生命周期托管的bean需要停止。
                if (wasManaged && bean._bean instanceof LifeCycle)
                {
                    try
                    {
                        stop((LifeCycle)bean._bean);
                    }
                    catch(RuntimeException | Error e)
                    {
                        throw e;
                    }
                    catch (Exception e)
                    {
                        throw new RuntimeException(e);
                    }
                }
                return true;
            }
            return false;
        }
    

    2.4 插播Container管理bean的规则

    通过前面的doStart和addBean可以基本确定Container管理bean的如下几条规则:

    ContainerLifeCycle是对容器化bean组件的一个生命周期的实现。

    bean可以作为托管bean或未托管bean放入ContainerLifeCycle里面。

    托管bean的启动停止和销毁由ContainerLifeCycle控制;未托管主要是为了dump,它们的生命周期必须独立管理。

    当一个没有指定类型具有生命周期的bean加入到ContainerLifeCycle,ContianerLifeCycle可以推断它的类型:

    (1)如果增加的bean运行中,它将以未托管类型加入container;

    (2)如果增加的bean未运行且container也未运行,它将以AUTO类型加入container;

    (3)如果增加的bean未运行且container在启动中,它将以托管类型加入container;

    (4)如果增加的bean未运行且container已经启动,它将以未托管类型加入container;

    当container已经启动,所有的托管bean也应该启动。

    任何AUTO类型的bean都将依据它们的状态被分为托管或未托管,如果已经启动则为未托管,否则将启动它们然后设置为托管类型。

    Contianer启动之后添加的bean将不会被启动,它们的状态需要显式管理。

    当停止Container的时候,只有被这个Container启动的bean才会停止。

    如果一个bean被多个Container共享,那么该bean只能是未托管的,即在增加之前,应该被启动

    2.4.1 实例

    2.5 manage和unmanage

     manage是设置bean为托管类型,unmanage设置bean为未托管类型。

    可以理解为两个相反的操作,需要注意如果被设置的bean是个Container,则需要将当前_listeners里面所有类型为InheritedListener的监听器添加到该bean里面或从该bean里面移除。

    // 托管bean
    private void manage(Bean bean)
        {
            if (bean._managed!=Managed.MANAGED)
            {
                bean._managed=Managed.MANAGED; // 设置bean为托管
    
                if (bean._bean instanceof Container)
                {
                    for (Container.Listener l:_listeners)
                    {
                        if (l instanceof InheritedListener) // 如果当前bean的listener里面有是InheritedListener需要增加到bean的_beans列表中
                        {
                            if (bean._bean instanceof ContainerLifeCycle)
                                ((ContainerLifeCycle)bean._bean).addBean(l,false);
                            else
                                ((Container)bean._bean).addBean(l);
                        }
                    }
                }
    
                if (bean._bean instanceof AbstractLifeCycle)
                {
                    ((AbstractLifeCycle)bean._bean).setStopTimeout(getStopTimeout());
                }
            }
        }
    
    // 未托管bean    
    private void unmanage(Bean bean)
        {
            if (bean._managed!=Managed.UNMANAGED)
            {
                if (bean._managed==Managed.MANAGED && bean._bean instanceof Container)
                {
                    for (Container.Listener l:_listeners)
                    {  // 如果监听器是InheritedListener,需要将其从未托管的bean中移除
                        if (l instanceof InheritedListener)
                            ((Container)bean._bean).removeBean(l);
                    }
                }
                bean._managed=Managed.UNMANAGED;
            }
        }
    

      

    2.6 addEventListener和removeEventListener

    两个是相反的操作,一个是增加Listener,另一个是删除Listener。

    如果待操作的Listener是InheritedListener子类,需要级联操作。

    @Override
        public void addEventListener(Container.Listener listener)
        {
            if (_listeners.contains(listener))
                return;
            
            _listeners.add(listener);
    
            // 新加的Listener需要被告知所有bean
            for (Bean b:_beans)
            {
                listener.beanAdded(this,b._bean);
    
                // 如果是InheritedListener需要增加到bean为Container的_beans列表中
                if (listener instanceof InheritedListener && b.isManaged() && b._bean instanceof Container)
                {
                    if (b._bean instanceof ContainerLifeCycle)
                         ((ContainerLifeCycle)b._bean).addBean(listener, false);
                     else
                         ((Container)b._bean).addBean(listener);
                }
            }
        }
    
      @Override
        public void removeEventListener(Container.Listener listener)
        {
            if (_listeners.remove(listener))
            {
                // remove existing beans
                for (Bean b:_beans)
                {
                    listener.beanRemoved(this,b._bean);
                    // 与增加相反,需要级联移除
                    if (listener instanceof InheritedListener && b.isManaged() && b._bean instanceof Container)
                        ((Container)b._bean).removeBean(listener);
                }
            }
        }  

    2.7 updateBean  

    最后ContainerLifeCycle还提供了重载的updateBean,入参一般是一个老bean和一个新bean。

    一般操作都是先删除老bean,然后增加新bean,都是复用上面提到的removeBean和addBean,不在详细描述。 

  • 相关阅读:
    迭代器(Iterator)的使用
    xml转array
    linux 常用命令
    yii2 httpClient的用法
    将普通用户添加到sudo
    yii2 注册一个新事件(trigger Event)
    解决IDEA输入法输入中文候选框不显示问题(亲测谷歌拼音完美解决问题)
    5个用/不用GraphQL的理由
    Linux 用户必须知道的 14 个常用 Linux 终端快捷键
    java执行系统命令, 返回执行结果
  • 原文地址:https://www.cnblogs.com/lujiango/p/8361415.html
Copyright © 2020-2023  润新知