Jetty - Container源碼分析

1. 描述

Container提供管理bean的能力。html

基於Jetty-9.4.8.v20171121。java

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的增長和刪除事件。ide

 

1.2 類圖

從類圖能夠看出,Container與LifeCycle接口很相似,都是不少組件的基本特徵,其默認實現是ContainerLifeCycle。源碼分析

2. ContainerLifeCycle

1.2類圖能夠看出ContainerLifeCycle不只是Container的默認實現,並且也是不少組件(Connector,Handler等)默認實現的父類。this

2.1 類圖

 

ContainerLifeCycle天然要實現Container接口; debug

ContainerLifeCycle繼承AbstractLifeCycle,而AbstractLifeCycle裏面實現了LifeCycle的模板啓停方法start和stop;rest

繼承AbstractLifeCycle的子類只須要實現AbstractLifeCycle中增長的doStart和doStop實現子類具體的啓動和中止,具體請參考【Jetty - LifeCycle源碼分析】htm

ContainerLifeCycle.Bean:內部類,表示管理的Bean對象。對象

ContainerLifeCycle.Managed:內部類,被管理的Bean有幾種類型:POJO,MANAGED,UNMANAGED,AUTO。blog

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,不在詳細描述。 

相關文章
相關標籤/搜索