【spring原始碼】八、getBean預覽

hancoder發表於2020-12-20

getBean

流程:

doGetBean

  • getSingleton1
    • singletionObject.get(beanName);有則直接返回
    • earlySingletonObjects.get(beanName);有則直接返回
    • singletonFactories.get(beanName);沒有就直接返回
      • singletonFactories.get(beanName);獲取到了工廠
      • singletonObject=singletonFactory.getObject();
      • earlySingletonObjects.put(beanName,singletonObject );
      • singletonFactories.remove(beanName);
  • getSingleton2 上面獲取不到才執行這裡
    • singletonFactory.getObject(){ create(); }
      • doCreateBean
        • ①createBeanInstance
        • ②addSingletonFactory((beanName,
          singletonFactory=new ObjectFactory(){ getObject(){ getEarlyBeanReference(); } }) // 第一次建立的時候把工廠加進去
          • singletonFactories.put(beanName, singletonFactory);
          • earlySingletonObjects.remove(beanName)
        • ③populateBean
        • ④initlizeBean
    • singletonObject.put

doGetBean

doGetBean方法內容有點多,這個方法非常重要,不僅僅針對迴圈依賴,甚至整個spring bean生命週期中這個方法也有著舉足輕重的地位

呼叫棧:

  • getBean()
  • doGetBean

為了解釋迴圈依賴,假如A類有B屬性,B類有A屬性,在原始碼中還會標明spring是在哪裡解決的迴圈依賴,與對應返回值的地方。迴圈依賴總結的內容在附錄

  • 第一個getSingleton是從快取獲取
  • 第二個getSingleton才是例項化bean,他的第二個引數是傳入一個createBean
//public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
protected <T> T doGetBean(
    final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)throws BeansException {

    // 提取對應的beanName // 傳入的引數name可能是別名,也可能是FactoryBean,所以需要進行一系列的解析,包括解析內容包括如下內容
    /*
		取出FactoryBean的修飾符,也就是如果name="&aa",name會首先去除&而使name="aa"
		取指定alias所表示的最終BeanName,例如別名A指向名稱為B的bean則返回B;若別名A指向別名B,別名B又指向名稱為C的bean則返回C
	*/
    final String beanName = transformedBeanName(name);
    Object bean;//定義了一個物件,用來存將來返回出來的bean


    /*
    檢查快取中或者例項工廠中是否有對應的例項
    為什麼首先會使用這段程式碼呢?因為建立單例bean的時候會存在依賴注入的情況,而在建立依賴的時候為了避免迴圈依賴,
    spring建立bean的原則是不等bean建立完成就將建立bean的ObjectFactory提早曝光,
    也就是將ObjectFactory假如到快取中,一旦下個bean建立時候需要依賴上個bean就直接使用ObjectFactory


    */
    // 從快取中獲取,獲取不到才建立。只要建立好的Bean都會被快取起來,保證單例項Bean只會被建立一次//第一次獲取應該是獲取不到的,返回null,之後繼續向下getObject (迴圈依賴第二次的時候才能返回值)
    //------------deGetBean-1------------
    // 直接嘗試從快取中獲取singletonFactories中的ObjectFactory中獲取// 快取獲取的地方在於第一個getSingleton裡的singletonObjects.get(beanName);
    // 注:迴圈依賴:①A注入B,②B注入A,③A又去建立。這裡①的時候是不進入第一個getSingleton的,而③是進入第一個getSingleton的
    // 這是第一個getSingleton(
    Object sharedInstance = getSingleton(beanName);//過載getSingleton(beanName, true);//這時沒有傳入工廠
    /*
        ⑩①finish階段getSingleton有返回值的有(即快取中有):internalConfigurationAnnotationProcessor、internalAutowiredAnnotationProcessor、internalRequiredAnnotationProcessor、
        internalCommonAnnotationProcessor、internalAutoProxyCreator
        */

    // ------------deGetBean-2------------
    //1、在spring初始化完成後[程式設計師]呼叫getBean(“x”)的時候得到的sharedInstance 就不等於null;
    //2、迴圈依賴的時候第二次獲取物件的時候這裡也不等於空;比如X 依賴 Y;Y依賴X;spring做初始化第一次執行到這裡的時候X 肯定等於null,然後接著往下執行,當執行到屬性注入Y的時候,Y也會執行到這裡,那麼Y也是null,因為Y也沒初始化,Y也會接著往下執行,當Y執行到屬性注入的時候獲取容器中獲取X,也就是第二次執行獲取X;這個時候X則不為空;放到factoryBean中講
    if (sharedInstance != null && args == null) {//如果從快取中拿到了,之前已經建立過了

        // 檢查當前bean是否是FactoryBean型別的bean,如果是,那麼就需要呼叫它的#getObject()作為返回值
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);//如果是工廠bean的話不發生改變直接回來//finish階段的bean都直接返回
    }
    //===========快取中沒有,開始建立======
    else {
        /*因為有些bean之前沒有呼叫過getBean,所以沒有註冊,從快取中拿不到,比如:
                internalEventListenerProcessor、internalEventListenerFactory、mainOfAOP、calculator、logAspects
                */
        // ------------deGetBean-3------------
        /*
        首先這裡是判斷當前的類是不是正在建立的原型集合當中,即裡面只會存原型,首先單例的bean肯定不在裡面,單例的bean返回false;
        再就是即使這個bean是原型也很少會在這裡就存在**正在建立的原型集合**當中。因為不管單例還是原型,bean在建立的過程中會add到這個集合當中,但是建立完成之後就會從這個集合remove掉(關於這個文章後面有證明),原型情況第一次建立的時候會add到這個集合,但是不是在這裡,而是在後面的建立過程中add,所以這裡肯定不會存在,即使後面過程中add到這個集合了,但是建立完成之後也會remove掉,故而下一次例項化同一個原型bean(原型可以例項化無數次)的時候當程式碼執行到這裡也不可能存在集合當中了;除非迴圈依賴會在bean還沒有在這個集合remove之前再次判斷一次,才有可能會存在,故而我前面說了一般情況下這裡都返回false;
        那麼單例情況我們已經說了一定返回false,原型情況只有迴圈依賴才會成立,但是隻要是正常人就不會對原型物件做迴圈依賴的;即使你用原型做了迴圈依賴這裡也出拋異常(因為if成立,進入分支 throw exception)
        只有在單例情況才回嘗試解決迴圈依賴,原型模式情況下,如果存在A中有B的屬性,B中有A的屬性,那麼當依賴注入的時候,就會產生當A還麼起床就完的時候對於B的建立再次返回建立A,造成迴圈依賴,跳不出去
        */
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // 如果beanDefinitionMap中也就是在所有一級載入的類中不包括beanName則嘗試從parentBeanFactory中檢測
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            String nameToLookup = originalBeanName(name);
            // 遞迴到beanFactory中尋找
            if (args != null) {
                // Delegation to parent with explicit args.
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else {
                // No args -> delegate to standard getBean method.
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
        }

        // 如果不是僅僅做型別檢查則是建立bean,這裡要做記錄
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        try {
            // 將儲存XML配置檔案的GernericBeanDefinition轉換為RootBeanDefinition,如果指定beanName是子bean的話同時會合並父類的相關屬性
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            String[] dependsOn = mbd.getDependsOn();
            // 若存在依賴則需要遞迴例項化依賴的bean
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {throw ...;}
                    // 快取依賴呼叫
                    registerDependentBean(dep, beanName);
                    getBean(dep);
                }
            }
            // 例項化依賴的bean後便可以例項化mbd本身了

            //------------doGetBean-4------------ //建立單例bean例項 
            if (mbd.isSingleton()) {// 判斷當前bean是否單例
                //下面第二次getSingleton()代表獲取單例項物件,但我們在內部程式碼頭一次獲取的時候肯定沒有這個單例項物件,就需要呼叫對應的getObject()方法進行建立
                // 這個 getSingleton和之前的 getSingleton不一樣,引數不一樣,是過載
                //下面使用lambda表示式傳入singletonFactory。ObjectFactory是一個介面,裡面有一個待實現的方法getObject()
                //每個bean都有一個他自己的工廠,即工廠是自己的,但是我們容器中的工廠是Listable工廠,即工廠的組合。這個前面也提過,beanFactory只能返回一個bean,但DefaultListableBeanFactory可以返回多個bean 
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {//從這裡進入getSingleton,並傳入
                    @Override // getObject()裡呼叫了createBean()
                    public Object getObject() throws BeansException {
                        try {
                            // 注:迴圈依賴的①會執行這裡,②也會,但③不會。但是在createBean裡①和②返回地方也不一樣
                            return createBean(beanName, mbd, args);//createBean建立 // 好了我們可以取下面第二個getSingleton裡看了
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            destroySingleton(beanName);
                            throw ex;
                        }
                    }
                });
                // 同上
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

            }else if (mbd.isPrototype()) {//多例的
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }else { //指定的scope上例項化bean
                String scopeName = mbd.getScope();
                final Scope scope = this.scopes.get(scopeName);
                if (scope == null) {throw... ;}
                try {
                    Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
                        @Override
                        public Object getObject() throws BeansException {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            }
                            finally {
                                afterPrototypeCreation(beanName);
                            }
                        }
                    });
                    bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {throw ...;}
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // 檢查需要的型別是否符合bean的實際型別
    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
        try {
            return getTypeConverter().convertIfNecessary(bean, requiredType);
        }
        catch (TypeMismatchException ex) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    return (T) bean;//finish階段直接return的有
}

我覺得這裡的重點是每個bean呼叫getSingleton()時候都會用lambda表示式建立一個自己的工廠傳進去。這個地方不懂的話debug時候也很繞

//每個bean都有一個他自己的工廠,即工廠是自己的,但是我們容器中的工廠是Listable工廠,即工廠的組合。這個前面也提過,beanFactory只能返回一個bean,但DefaultListableBeanFactory可以返回多個bean

getSingleton

呼叫棧:

  • doGetBean
    • getSingleton1
      • singletionObject.get(beanName);有則直接返回
      • earlySingletonObjects.get(beanName);有則直接返回
      • singletonFactories.get(beanName);沒有就直接返回,有則執行下面3條
        • singletonObject=singletonFactory.getObject();
        • earlySingletonObjects.put(beanName,singletonObject );
        • singletonFactories.remove(beanName);
    • getSingleton2 上面獲取不到才執行這裡
      • singletonFactory.getObject(){ create(); }
        • doCreateBean
          • createBeanInstance
          • addSingletonFactory((beanName,
            singletonFactory=new ObjectFactory(){ getObject(){ getEarlyBeanReference(); } }) // 第一次建立的時候把工廠加進去
            • singletonFactories.put(beanName, singletonFactory);
            • earlySingletonObjects.remove(beanName)
          • populateBean
          • initlizeBean
      • singletonObject.put

介紹:單例在spring的同一個容器中只會被建立一次,後續再獲取bean直接從單例快取中獲取,當然這裡也只是嘗試載入,首先嚐試從換從中載入,然後再次嘗試從singletonFactories中載入。因為在建立單例bean的時候會存在依賴注入的情況,而在建立依賴的時候為了避免迴圈依賴,spring建立bean的原則是不等bean建立完成就會將建立bean的ObjectFactory提前曝光假如到快取中,一旦下一個bean建立時需要依賴上個bean,直接使用ObjectFactory

  • singletonObject:1級map。用於儲存BeanName和建立bean例項之間的關係,bean name --> bean instance
  • earlySingleObjects:2級map。也是用於儲存BeanName和建立bean例項之間的關係,與singletonObject的不同之處在於,當一個例項bean被放到這裡面後,那麼當bean還在建立過程中,就可以通過getBean方法獲取到了,其目的是用來檢測迴圈引用
  • singletonFactories:3級map。用於儲存BeanName和建立bean工廠之間的關係,bean name --> ObjectFactory
  • registeredSingletons:用來儲存當前所有已經註冊的bean

getSingleton-1 迴圈依賴第二次獲取的地方

再次說明,執行順序是getSingleton-1,getSingleton-2,但我們一開始例項化的時候進入的是getSingleton-2,而從快取中拿的時候(或迴圈依賴)是從getSingleton-1中拿到的

  • 第一個getSingleton來自DefaultSingletonBeanRegistry.java,這個類被AbstractBeanFactory繼承

我們得先說說DefaultSingletonBeanRegistry中幾個重要的屬性

  • singletonObjects:用於存放完全初始化好的 bean,從該快取中取出的 bean 可以直接使用
  • earlySingletonObjects:提前曝光的單例物件的cache,存放原始的 bean 物件(尚未填充屬性),用於解決迴圈依賴
  • singletonFactories:單例物件工廠的cache,存放 bean 工廠物件,用於解決迴圈依賴
    • 三級map:提前建立代理物件
    • 二級map:A有屬性B,B有屬性C,C有屬性A,那BC都建立了各自的一個A代理物件。所以我們就發明個二級map,保證代理物件只有一個
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	...
	// 從上至下 分表代表這“三級快取”,3個Map
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); //一級快取
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); // 二級快取
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 三級快取
	...
	
    
     // 2個Set
	/** Names of beans that are currently in creation. */
	// 這個快取也十分重要:它表示bean建立過程中都會在裡面呆著~
	// 它在Bean開始建立時放值,建立完成時會將其移出~
	private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

	/** Names of beans that have already been created at least once. */
	// 當這個Bean被建立完成後,會標記為這個 注意:這裡是set集合 不會重複
	// 至少被建立了一次的  都會放進這裡~~~~
	private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
}

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {

    // 程式設計師一般從這個getSingleton中就能得到bean。但在註冊容器的時候是拿不到的,除非有單例迴圈依賴
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {

        /*
        1 首先嚐試從singletonObjects中獲取,如果獲取到了直接return
        2 再嘗試從earlySingletonObjects中獲取,如果獲取到了直接return
        3 再嘗試從singletonFactories裡獲取ObjectFactory,
        然後呼叫ObjectFactory#getObject()來建立bean,並放到earlySingletonObjects中,從singletonFactories中移除掉這個ObjectFactory,
        我們一般在容器初始化後使用getBean一般到這就返回了
        */
            // 1 檢查快取中是否存在例項
   
    
            Object singletonObject = this.singletonObjects.get(beanName);
            // 如果快取中為空 且 
            /*
          對於isSingletonCurrentlyInCreation(beanName),迴圈依賴的時候,這裡是滿足的,具體原因看beforeSingletonCreation()
             這個時候x注入y,建立y時y注入x,獲取x的時候,滿足isSingletonCurrentlyInCreation;
          而沒有迴圈依賴的時候,第一個建立的時候是進不來的
         */
        if (singletonObject == null &&  //double check
            isSingletonCurrentlyInCreation(beanName)) {  // 第一次X的時候這個條件不滿足

            // 鎖定全域性變數進行處理
            synchronized (this.singletonObjects) {
                // 2 先嚐試從3級快取earlySingletonObjects中獲取
                // 如果此bean正在載入則不處理
                singletonObject = this.earlySingletonObjects.get(beanName); // 迴圈依賴我們的最終目的是放到earlySingletonObjects裡
                // 如果正在建立就直接跳過了 // 後續的所有記憶體操作都只為了迴圈依賴檢測時候使用,也就是allowEarlyReference為true的時候才使用
                if (singletonObject == null && allowEarlyReference) {
                    // 3 先嚐試singletonFactories裡獲取ObjectFactory
                    // 當某些方法需要提前初始化的時候會呼叫addSingletonFactory方法對應的ObjectFactory初始化策略儲存在singletonFactories
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        // 呼叫預先設定的getObject,得到返回的物件
                        singletonObject = singletonFactory.getObject();//但是這裡拿到的還是FactoryBean
                        // 記錄在快取中,earlySingletonObjects和singletonFactories互斥
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }

  • 先從一級快取singletonObjects中去獲取。(如果獲取到就直接return)
  • 如果獲取不到或者物件正在建立中(isSingletonCurrentlyInCreation()),那就再從二級快取earlySingletonObjects中獲取。(如果獲取到就直接return)
    • 新增:向裡面新增資料只有一個地方,就是上面說的getSingleton()裡從三級快取裡挪過來
    • 移除addSingleton、addSingletonFactory、removeSingleton從語義中可以看出新增單例、新增單例工廠ObjectFactory的時候都會刪除二級快取裡面對應的快取值,是互斥的
  • 如果還是獲取不到,且允許singletonFactories(allowEarlyReference=true)通過getObject()獲取。就從三級快取singletonFactory.getObject()獲取。(如果獲取到了就從singletonFactories中移除,並且放進earlySingletonObjects。其實也就是從三級快取移動(是剪下、不是複製哦~)到了二級快取)
    • 加入singletonFactories三級快取的前提是執行了構造器,所以構造器的迴圈依賴沒法解決

getSingleton-2 迴圈依賴第一次放入的地方

要點:

  • 嘗試從singletonObjects中獲取,獲取不到
  • beforeSingletonCreation():把beanName加入到beforeSingletonCreation那個Set
  • 呼叫傳進來的singletonFactory.getObject(),他裡面有createBean()
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "'beanName' must not be null");
    synchronized (this.singletonObjects) {// 全域性變數需要同步
        //getSingleton2 -1------------
        // 根據name拿到快取中的bean // 首先檢查對應的bean是否已經載入過,因為singleton模式其實就是複用已建立的bean
        Object singletonObject = this.singletonObjects.get(beanName);//在第一個getSingleton裡已經get過一次了,這裡更拿不到了吧
        //getSingleton2 -2------------
        // 如果為空,就去進行singleton的bean的初始化
        if (singletonObject == null) {
            //getSingleton2 -3 判斷當前例項化的bean是否正在銷燬的集合裡面;spring不管銷燬還是建立一個bean的過程都比較繁瑣,都會先把他們放到一個集合當中標識正在建立或者銷燬;所以如果你理解了前面那個正在建立集合那麼這個正在銷燬集合也就理解了;
            if (this.singletonsCurrentlyInDestruction) {throw...;}
            
            
            //getSingleton2 -4------------  
            // 把beanName放到singletonsCurrentlyInCreation那個Set中,key為beanName,代表開始建立但還沒建立完畢,為了迴圈依賴服務
            // 注意並不是放到early那個map
            // 因為spring不管建立原型bean還是單例bean,當他需要正式建立bean的時候他會記錄一下這個bean正在建立(add到一個set集合當中);故而當他正式建立之前他要去看看這個bean有沒有正在被建立(是否存在集合當中); 為什麼spring要去判斷是否存在這個集合呢?原因很多除了你們能想到了(你們能想到的基本不會出現,比如併發啊,重複建立什麼的,因為他已經做了嚴格併發處理)
            beforeSingletonCreation(beanName); // 如果一個bean建立完成就從這個list集合remove // 到這連構造方法都沒執行,僅僅說明要建立
            /* 看一下這個方法的原始碼
            beforeSingletonCreation(beanName){
                if (!this.inCreationCheckExclusions.contains(beanName) &&  // 判斷當前需要建立的bean是否在Exclusions集合,被排除的bean,程式設計師可以提供一些bean不被spring初始化(哪怕被掃描到了,也不初始化),那麼這些提供的bean便會存在這個集合當中;
                	!this.singletonsCurrentlyInCreation.add(beanName)) { //如果當前bean不在排除的集合當中那麼則這個bean新增到singletonsCurrentlyInCreation(當然這裡只是把bean名字新增到集合,為了方便我們直接認為把bean新增到集合吧,因為他能根據名字能找打對應的bean)
                	
                    throw new BeanCurrentlyInCreationException(beanName);
				}
            }
            */
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<Exception>();
            }
            try {
                //getSingleton2 -5------------
                // 初始化bean 呼叫getObject()方法,這個方法裡有createBean()
                singletonObject = singletonFactory.getObject();//工廠//呼叫傳進來工廠的getObject()方法
                newSingleton = true;
                // 執行完的bean是完整的
                
            }catch (IllegalStateException,BeanCreationException ex) {...;}
            finally {
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = null;
                }
                // 從singletonsCurrentlyInCreation的map中移除
                afterSingletonCreation(beanName);//this.singletonsCurrentlyInCreation.remove(beanName))
            }
            if (newSingleton) {
                //呼叫完後加入到單例池中,快取起來,下次再getBean就直接返回了
                addSingleton(beanName, singletonObject);
            }
        }
        return (singletonObject != NULL_OBJECT ? singletonObject : null);
    }
}

beforeSingletonCreation(beanName)–singletonsCurrentlyInCreation-map

首先我們觀察他的位置:doGetBean裡第二個getSingleton裡,getSingleton裡傳入了lambda工廠,這個過程裡有getObject方法,getObject裡有createBean方法,這是我們正常的建立bean的流程。而beforeSingletonCreation在第二個getSingleton()中、getObject()前。也就是說,在createBean前,已經把要建立的bean的資訊放到了"正在建立bean"singletonsCurrentlyInCreation的集合中。

注意是第二個getSingleton中,第一個getSingleton之後。第一個getSingleton用於檢測是否在建立中,第二個getSingleton用於檢測把當前物件加入"正在建立"+開始建立createBean

beforeSingletonCreation(beanName){
    if (!this.inCreationCheckExclusions.contains(beanName) &&  // 判斷當前需要建立的bean是否在Exclusions集合,被排除的bean,程式設計師可以提供一些bean不被spring初始化(哪怕被掃描到了,也不初始化),那麼這些提供的bean便會存在這個集合當中;
        !this.singletonsCurrentlyInCreation.add(beanName)) { //如果當前bean不在排除的集合當中那麼則這個bean新增到singletonsCurrentlyInCreation(當然這裡只是把bean名字新增到集合,為了方便我們直接認為把bean新增到集合吧,因為他能根據名字能找打對應的bean)

        throw new BeanCurrentlyInCreationException(beanName);
    }
}

this.singletonsCurrentlyInCreation.remove(beanName))對應的afterSingletonCreation(String beanName)是在第2個getSingleton建立完完整的bean後。

protected void afterSingletonCreation(String beanName) {
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
        throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    }
}

createBean

// 
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;

    // Make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved Class
    // which cannot be stored in the shared merged bean definition.
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    // Prepare method overrides.
    try {
        mbdToUse.prepareMethodOverrides();
    }catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);
    }

    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        // 給例項化後置處理器()一個返回代理物件的機會
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex);
    }

    // 前面後置處理器沒有返回代理物件,我們建立正常的普通物件
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);

    return beanInstance;
}

resolveBeforeInstantiation()

註冊後置處理器的時候會進來這裡

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {//例項化之前解析//後置處理器嘗試返回物件
    Object bean = null;
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // Make sure bean class is actually resolved at this point.
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);//BeforeInstantiation例項化前
                //如果返回值不為null,那麼就沿用PostBeanProcessor //internal的時候實際上返回結果為null,所以resolveBeforeInstantiation函式整體在internal階段是返回null的
                if (bean != null) {//calculator這裡會為null
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);//AfterInitialization初始化後//呼叫完Calculator後 來到這裡
                }
            }
        }
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
}

因為在註冊internalAutoProxyCreator時候並沒有呼叫applyBeanPostProcessorsAfterInitialization這句,也就是resolveBeforeInstantiation()實際上是沒有作用的,而resolveBeforeInstantiation要等到註冊普通bean的才起作用,所以我們放到後面⑪finishBeanFactoryIntialization講。

public abstract class AbstractAutoProxyCreator extends ProxyConfig
    implements SmartInstantiationAwareBeanPostProcessor, BeanClassLoaderAware, BeanFactoryAware,
Ordered, AopInfrastructureBean {
    
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        // 生成快取key
        Object cacheKey = getCacheKey(beanClass, beanName);

        if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {
            // 是否在已經增強的bean裡,debug的時候不在
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null;
            }
            // 判斷是不是PointCut/Advisor/AopInfrastructureBean/Advice/AopInfrastrureBean/Aspect
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { // shouldSkip是找到候選的Advisors,增強器包裝為了Advisor,型別是InstantiationMedelAwarePointcutAdvisor,判斷他是不是AspectJPointcutAdvisor型別的,不是。
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null;
            }
        }

        // Create proxy here if we have a custom TargetSource.
        // Suppresses unnecessary default instantiation of the target bean:
        // The TargetSource will handle target instances in a custom fashion.
        if (beanName != null) {
            TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
            if (targetSource != null) {
                this.targetSourcedBeans.add(beanName);
                Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
                Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
                this.proxyTypes.put(cacheKey, proxy.getClass());
                return proxy;
            }
        }

        return null;
    }

doCreateBean

呼叫棧:

  • doGetBean
    • getSingleton1
      • singletionObject.get(beanName);有則直接返回
      • earlySingletonObjects.get(beanName);有則直接返回
      • singletonFactories.get(beanName);沒有就直接返回
        • singletonObject=singletonFactory.getObject();
        • earlySingletonObjects.put(beanName,singletonObject );
        • singletonFactories.remove(beanName);
    • getSingleton2 上面獲取不到才執行這裡

      • singletonFactory.getObject(){ create(); }
        • doCreateBean
          • 1)createBeanInstance
          • 2)addSingletonFactory((beanName,
            singletonFactory=new ObjectFactory(){ getObject(){ getEarlyBeanReference(); } }) // 第一次建立的時候把工廠加進去
            • singletonFactories.put(beanName, singletonFactory);
            • earlySingletonObjects.remove(beanName)
          • 3)populateBean
          • 4)initlizeBean
      • singletonObject.put

流程:

  • 在前面已經執行過getSingleton2,在那裡把beanName放入了singletonsCurrentlyInCreation這個Set中
// AbstractAutowireCapableBeanFactory
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
    throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        // doCreateBean-1 
        // 僅僅完成了物件建立,剩下都沒做 // 將bd轉換成BeanWrapper
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    // 從Wrapper中獲取原生物件,這個時候這個bean就有地址值了,就能被引用了
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
    }

    // Allow post-processors to modify the merged bean definition.
    // 和迴圈依賴無關
    synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
            try {
                applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
            }catch (Throwable ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);
            }
            mbd.postProcessed = true;
        }
    }

    // doCreateBean-2  快取一個物件去解決迴圈依賴(在屬性注入之前) 
    // earlySingletonExposure 用於表示是否”提前暴露“原始物件的引用,用於解決迴圈依賴
    // 迴圈依賴中第二次建立A時不是直接建立,而是通過放入快取中的ObjectFactory來建立物件
    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    boolean earlySingletonExposure = (mbd.isSingleton() && 
                                      this.allowCircularReferences &&
                                      isSingletonCurrentlyInCreation(beanName));//在getSingleton2中被新增
    if (earlySingletonExposure) {
        // 為避免後期迴圈依賴,可以在bean初始化完成前將建立例項的ObjectFactory加入工廠
        // 從二級earlySingletonObjects中移除(在這沒加過)
        // 加入到三級singletonFactories,傳入了正在建立bean的引用
        addSingletonFactory(beanName,
                            new ObjectFactory(){// 既然傳進去了,裡面肯定會回撥getObject()
                                public Object getObject() throws BeanException{
                                    // 對bean再一次依賴引用,主要應用SmartInstaniationAware BeanPost Processor
                                    // 其中我們熟知的AOP就是在這裡將advice動態織入bean中,若沒有則直接返回bean,不做任何處理
                                    // 獲取早期bean的引用
                                    return getEarlyBeanReference(beanName, mbd, bean));//傳入了bean
                                    // 還記得doGetBean裡的第二個getSingleton也傳入了一個ObjectFactory#getObject(){createBean();}
                                    // 而這裡doCreateBean裡傳入的是ObjectFactory#getObject(){getEarlyBeanReference();}
                                }
                            });
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        // doCreateBean-3
        // 屬性填充
        populateBean(beanName, mbd, instanceWrapper);
        // doCreateBean-4 //呼叫初始化方法,如Aware、before-init後置處理器、init-method、after-init後置處理器
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    catch (Throwable ex) {
        if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
            throw (BeanCreationException) ex;
        }else {
            throw new BeanCreationException(
                mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
        }
    }

    // 建立bean結束,
    if (earlySingletonExposure) {
        // 此時一級快取肯定還沒資料,但是呢此時候二級快取earlySingletonObjects也沒資料
        // 呼叫getSingleton1,false代表不去3級快取查了
        // 這裡獲得的是提前產生的代理物件
        Object earlySingletonReference = getSingleton(beanName, false);
        // earlySingletonReference只有在檢測到有迴圈依賴的情況下才會不為空
        if (earlySingletonReference != null) {
            // 這個意思是如果經過了initializeBean()後,exposedObject還是木有變,那就可以大膽放心的返回了
            // initializeBean會呼叫後置處理器,這個時候可以生成一個代理物件,那這個時候它哥倆就不會相等了 走else去判斷吧
            // 如果exposedObject沒有在初始化方法中被改變,也就是沒有被增強
            if (exposedObject == bean) {
                // 通常都是true
                exposedObject = earlySingletonReference;
            }//  allowRawInjectionDespiteWrapping這個值預設是false
            // hasDependentBean:若它有依賴的bean 那就需要繼續校驗了~~~(若沒有依賴的 就放過它~)
            else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                // 拿到它所依賴的Bean們~~~~ 下面會遍歷一個一個的去看~~
                String[] dependentBeans = getDependentBeans(beanName);
                Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
                // 一個個檢查它所以Bean
                // removeSingletonIfCreatedForTypeCheckOnly這個放見下面  在AbstractBeanFactory裡面
                // 簡單的說,它如果判斷到該dependentBean並沒有在建立中的了的情況下,那就把它從所有快取中移除~~~  並且返回true
                // 否則(比如確實在建立中) 那就返回false 進入我們的if裡面~  表示所謂的真正依賴
                //(解釋:就是真的需要依賴它先例項化,才能例項化自己的依賴)
                for (String dependentBean : dependentBeans) {
                    if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
                        actualDependentBeans.add(dependentBean);
                    }
                }
                // 若存在真正依賴,那就報錯(不要等到記憶體移除你才報錯,那是非常不友好的) 
                // 這個異常是BeanCurrentlyInCreationException,報錯日誌也稍微留意一下,方便定位錯誤~~~~
                if (!actualDependentBeans.isEmpty()) {
                    throw new 。。。;
                }
            }
        }
    }

    // Register bean as disposable.
    try {
        registerDisposableBeanIfNecessary(beanName, bean, mbd);
    }catch (BeanDefinitionValidationException ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }

    return exposedObject;
}

// 雖然是remove方法 但是它的返回值也非常重要
// 該方法唯一呼叫的地方就是迴圈依賴的最後檢查處~~~~~
protected boolean removeSingletonIfCreatedForTypeCheckOnly(String beanName) {
    // 如果這個bean不在建立中  比如是ForTypeCheckOnly的  那就移除掉
    if (!this.alreadyCreated.contains(beanName)) {
        removeSingleton(beanName);
        return true;
    }
    else {
        return false;
    }
}
getEarlyBeanReference

上面doCreateBean中再建立空白的例項後,會執行一個放入3級map的操作,

// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                                  isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
    if (logger.isTraceEnabled()) {
        logger.trace("Eagerly caching bean '" + beanName +
                     "' to allow for resolving potential circular references");
    }
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}

addSingletonFactory是放入3級map的操作,這裡有個lambda表示式,但是addSingletonFactory裡並沒執行。這在很多地方點過,此時只是放入了lambda表示式,並未執行lambda表示式。也就是放入了ObjectFactory工廠,但是並沒有執行他的getObject()。執行時間是返回從b注入屬性a時返回a的getSingleton時執行。

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    synchronized (this.singletonObjects) {
        if (!this.singletonObjects.containsKey(beanName)) {
            this.singletonFactories.put(beanName, singletonFactory);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
}

//========包含的一個函式式介面=====================
@FunctionalInterface
public interface ObjectFactory<T> {
    T getObject() throws BeansException;
}

所以上面addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));這句程式碼的意思是new了個ObjectFactory物件,而且他物件有一個方法getObject(),而他裡面會呼叫getEarly方法,即getObject(){getEarlyBeanReference()}

在getEarlyBeanReference中,提前產生了代理物件。在AbstractAutoProxyCreator中實現,也就是說,在。

  • A填充屬性時,建立完B,然後執行Creator.getEarlyBeanReference(),裡面呼叫wrapIfNeccessay()。也就是說先執行getEarlyBeanReference,後執行wrapIfNeccessay。wrapIfNeccessay是正常執行的。getEarlyBeanReference裡會earlyProxyReferences.put(cacheKey,bean);
/**
	 * Obtain a reference for early access to the specified bean,
	 * typically for the purpose of resolving a circular reference.
	 * @param beanName the name of the bean (for error handling purposes)
	 * @param mbd the merged bean definition for the bean
	 * @param bean the raw bean instance
	 * @return the object to expose as bean reference
	 */
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
    // 這個bean是原始物件
    Object exposedObject = bean;
    // 開始對原始物件加工
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            // SmartInstantiationAwareBeanPostProcessor是後置處理器的子介面,我們普通的後置處理器是處理真正bean的,而這裡我們的bean並沒有生成出來,所以是使用這種後置處理器提前代理的
            // https://blog.csdn.net/u010634066/article/details/80348253
            if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
                SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
                // 傳入exposedObject加工後重新賦值exposedObject
                exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
            }
        }
    }
    return exposedObject;
}
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
    implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

    @Override
    public Object getEarlyBeanReference(Object bean, String beanName) {
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        // 這裡需要解釋為什麼放入原始物件,而不是放入代理物件:因為二級快取已經放了代理物件。另外一個作用是可以判斷是否提前生成了代理物件,在後面postProcessAfterInitialization()時會判斷if(earlyProxyReference.remove(cacheKey)!=bean){return wrapIfNecessary(bean,beanName,cacheKey)}
        this.earlyProxyReferences.put(cacheKey, bean);
        return wrapIfNecessary(bean, beanName, cacheKey);
    }


    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            Object cacheKey = getCacheKey(bean.getClass(), beanName);
            // 如果取出來是空,就!=bean,就可以代理。如果等於了,說明前面迴圈依賴的時候代理過了,無需重複代理
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

到這還剩下一個問題,singletonObject什麼時候放入或替換

什麼時候放入singletonObject

執行完createBean後,在第二個getSingleton方法的最後放入addSingleton(beanName, singletonObject);

1 createBeanInstance

建立bean例項,空殼子,屬性值都還沒設定。即指向了預設構造,但沒有執行getter setter

在這裡插入圖片描述

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    Class<?> beanClass = resolveBeanClass(mbd, beanName);

    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }

    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
        return obtainFromSupplier(instanceSupplier, beanName);
    }

    if (mbd.getFactoryMethodName() != null) {
        return instantiateUsingFactoryMethod(beanName, mbd, args);
    }

    // Shortcut when re-creating the same bean...
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
        synchronized (mbd.constructorArgumentLock) {
            if (mbd.resolvedConstructorOrFactoryMethod != null) {
                resolved = true;
                autowireNecessary = mbd.constructorArgumentsResolved;
            }
        }
    }
    if (resolved) {
        if (autowireNecessary) {
            return autowireConstructor(beanName, mbd, null, null);
        }else {
            return instantiateBean(beanName, mbd);
        }
    }

    // Candidate constructors for autowiring?
    // 如果是自動裝配,則推斷出來各種候選的構造方法
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
        mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        // 利用推斷出來的候選構造方法去例項化物件
        return autowireConstructor(beanName, mbd, ctors, args);
    }

    // Preferred constructors for default construction?
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        return autowireConstructor(beanName, mbd, ctors, null);
    }

    // No special handling: simply use no-arg constructor.
    // 沒有推斷出合適的構造方法(或者沒有提供特殊的構造方法),則使用預設的構造方法
    // 裡面利用反射來例項化
    return instantiateBean(beanName, mbd);
    /*
    beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);//進入
    
    constructorToUse = clazz.getDeclaredConstructor();
    return BeanUtils.instantiateClass(constructorToUse);//進入
    
    // BeanUtils.java
    ctor.newInstance(argsWithDefaultValues);
    */
}

2 addSingletonFactory(beanName,factory);

//doCreateBean-2
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 給earlySingletonExposure這個布林型別的變數賦值;這個變數的意義是——是否支援(開啟了)迴圈依賴;如果返回true則spring會做一些特殊的操作來完成迴圈依賴;如果返回false,則不會有特殊操作;
boolean earlySingletonExposure = (mbd.isSingleton() &&  //判斷當前例項化的bean是否為單例;再一次說明原型是不支援迴圈依賴的;因為如果是原型這裡就會返回false,由於是&&運算,整個結果都為false; 
                                  this.allowCircularReferences && // 整個全域性變數spring 預設為true;當然spring提供了api供程式設計師修改,這個在本文開頭筆者解釋過(筆者是通過修改spring原始碼來改變這個值為false),在沒有修改的情況下這裡也返回true
                                  isSingletonCurrentlyInCreation(beanName)); // 判斷當前正在建立的bean是否在正在建立bean的集合當中;還記得前文筆者已經解釋過singletonsCurrentlyInCreation這個集合現在裡面存在且只有一個x;故而也會返回true;
if (earlySingletonExposure) {//我們的單例一般都會進入if
    // 下面add的是工廠,而通過這個工廠可以得到半成品bean
    addSingletonFactory(beanName, 
                        ObjectFactory<?> singletonFactory = new ObjectFactory<?>(){
                            public T getObject(){//getObject();其實就是返回當前正在例項化的bean
                                //至於這個getEarlyBeanReference方法的程式碼,後面再來說
                                getEarlyBeanReference(beanName, mbd, bean);
                                /*
                                getEarlyBeanReference 的程式碼稍微複雜一點,可以簡單理解為下面這樣
                                getEarlyBeanReference(beanName, mbd, bean){
                                    return bean;
                                }
                                */
                            }
                        }
                       );
    
}
/*
其實這三種情況需要關心的只有第二種;

因為第一種是否單例一般都是成立的,因為如果是原型的迴圈依賴前面程式碼已經報錯了;壓根不會執行到這裡;

第三種情況也一般是成立,因為這個集合是spring操作的,沒有提供api給程式設計師去操作;而正常流程下程式碼執行到這裡,當前正在建立的bean是一定在那個集合裡面的;換句話說這三個條件1和3基本恆成立;

唯有第二種情況可能會不成立,因為程式設計師可以通過api來修改第二個條件的結果;

總結:spring的迴圈依賴,不支援原型,不支援構造方法注入的bean;預設情況下單例bean是支援迴圈依賴的,但是也支援關閉,關閉的原理就是設定allowCircularReferences=false(預設為true);spring提供了api來設定這個值
*/
// DefaultSingletonBeanRegistry.java
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
    
    Assert.notNull(singletonFactory, "Singleton factory must not be null");
    
    // singletonObjects 一級map
    synchronized (this.singletonObjects) {
        /*
        如果單例池中不存在才會add
        因為這裡主要為了迴圈依賴服務的程式碼
        如果bean存在單例池的話其實一級是一個完整的bean了
        一個完整的bean自然完成了屬性注入,迴圈依賴已經依賴上了
        所以如果這個物件已經是一個完整bean,或不需要關係,不需要進if
        因為不存在完成的bean,所以我們進入if看有沒有半成品bean
        */
        if (!this.singletonObjects.containsKey(beanName)) {
            // 把工廠物件put到二級map singletonFactories
            this.singletonFactories.put(beanName, singletonFactory);
            /* 
            從三級map中remove掉當前bean
             為什麼需要remove?拋開細節,這個三個map其實存的是同一個物件
             spring的做法是三個不能同時存在,如果1存了,則2和3就要remove
             反之亦然,現在既然put到了2級快取,1已經判斷沒有,3則直接remove
            */
            this.earlySingletonObjects.remove(beanName);//this.earlySingletonObjects.put(beanName, singletonObject);在第一個 getSingleton中
            this.registeredSingletons.add(beanName);
        }
    }
}

在這裡插入圖片描述在這裡插入圖片描述

3 populateBean

設定屬性值

4 initializeBean

會判斷是不是提前產生過代理物件,在AbstactAutoProxyCreator裡有一個earlyProxyReference屬性:提前代理引用的map。在beanPostProcessor裡會呼叫Creator.postProcessAfterInitialzation()然後會提前判斷是否需要執行wrapIfNecessary()

  • doCreateBean
    • 1)createBeanInstance 建立例項
    • 2)addSingletonFactory((beanName,
      singletonFactory=new ObjectFactory(){ getObject(){ getEarlyBeanReference(); } }) // 第一次建立的時候把工廠加進去
      • singletonFactories.put(beanName, singletonFactory);
      • earlySingletonObjects.remove(beanName)
    • 3)populateBean 屬性注入
    • 4)initlizeBean 初始化
      • invokeAwareMethods 注入Aware相關的set方法
      • applyBeanPostProcessorsBeforeInitialization 初始化前
      • invokeInitMethods 正常初始化
      • applyBeanPostProcessorsAfterInitialization 初始化後,AOP
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            public Object run() {
                AbstractAutowireCapableBeanFactory.this.invokeAwareMethods(beanName, bean);//0 預處理
                return null;
            }
        }, this.getAccessControlContext());
    } else {
        this.invokeAwareMethods(beanName, bean);//1 Aware
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);//2 before
    }

    try {
        this.invokeInitMethods(beanName, wrappedBean, mbd);//3 正常功能
    } catch (Throwable var6) {,,,; }

    if (mbd == null || !mbd.isSynthetic()) {
        wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//4 after
    }

    return wrappedBean;
}
initializeBean4-1 :invokeAwareMethods
AbstractAutowireCapableBeanFactory類;
private void invokeAwareMethods(final String beanName, final Object bean) {//對於後置處理器而言,他的初始化方法。
    if (bean instanceof Aware) {
        // 從下面的if我們也可以知道,我們的bean對應可以繼承哪些aware類
        // 獲取註冊的beanName
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        // 獲取該bean的類載入器
        if (bean instanceof BeanClassLoaderAware) {
            ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
        }
        // 獲取beanFactory
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}
//-------------------
類AbstractAdvisorAutoProxyCreator重寫了set方法;
//但這些後置處理器,只有internalAutoProxyCreator通過initlizeBean方法到達了setBeanFactory
public void setBeanFactory(BeanFactory beanFactory) {
    super.setBeanFactory(beanFactory);
    if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
        throw new IllegalArgumentException("AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
    } else {
        this.initBeanFactory((ConfigurableListableBeanFactory)beanFactory);//初始化工廠
    }
}
initializeBean4-2 :applyBeanPostProcessorsBeforeInitialization

對應給定bean,拿到所有後置處理器,執行這些後置處理器的的BeforeInitialization方法,嘗試看看這個bean有沒有對應的後置處理器能呼叫BeforeInitialization返回給這個bean一些內容(初始化前的操作),只要有一個BeforeInitialization方法返回值了,我們就return,不再執行試探的後置處理器。由此也可看出,後置處理器的BeforeInitialization方法很少能返回值。

呼叫棧:

  • getBean
  • doGetBean
  • getSingleton
  • getObject
  • docreateBean
  • initializeBean
  • applyBeanPostProcessorsBeforeInitialization
AbstractAutowireCapableBeanFactory;
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
    throws BeansException {//應用後置處理器的BeforeInitialization

    // 獲取init的後置處理器
    Object result = existingBean;//已經存在的bean
    for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {//拿到所有後置處理器,呼叫後置處理器對應的before
        result = beanProcessor.postProcessBeforeInitialization(result, beanName);
        if (result == null) {
            return result;
        }
    }
    return result;
}
initializeBean4-3 :invokeInitMethods

initBeanFactory()

呼叫棧:

  • invokeAwareMethods
  • setBeanFactory
  • initBeanFactory
AnnotationAwareAspectJAutoProxyCreator;
@Override
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {//重新包裝
    super.initBeanFactory(beanFactory);
    if (this.aspectJAdvisorFactory == null) {
        this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);//反射AspectJ通知工廠
    }
    this.aspectJAdvisorsBuilder =
        new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
}
initializeBean4-4 :After:

放到finish階段講解,因為對應後置處理器bean,通常沒有給這些後置處理器在初始化後處理的後置處理器

—初始化完成----以上是建立和註冊AnnotationAwareAspectJAutoProxyCreater這個bean的過程--------

他是InstantiationAwareBeanPostProcessor,也是一種後置處理器

((DefaultListableBeanFactory) beanFactory).alreadyCreated :5個internal

建立後置處理器例項完成。

最後

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean

返回

返回到

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>)

addSingleton(beanName, singletonObject);

最後返回到最初的呼叫處

org.springframework.context.support.PostProcessorRegistrationDelegate#registerBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, org.springframework.context.support.AbstractApplicationContext)

BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);

至此AnnotationAwareAspectJAutoProxyCreator建立成功並初始化

之後呼叫

sortPostProcessors(orderedPostProcessors, beanFactory);

registerBeanPostProcessors(beanFactory, orderedPostProcessors);

/** Register the given BeanPostProcessor beans.*/
private static void registerBeanPostProcessors(
    ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {


    for (BeanPostProcessor postProcessor : postProcessors) {
        beanFactory.addBeanPostProcessor(postProcessor);
    }
}

把建立並初始化好的internalAutoProxyCreator註冊到BeanFactory中(beanFactory就是容器,容器大類上分兩種,beanFactory和applicationContext)

然後,註冊沒實現優先順序介面的BeanPostProcessor;

以上就是建立、初始化和註冊AnnotationAwareAspectJAutoProxyCreator的過程

相關文章