spring源碼解析之如何從spring中獲取一個bean(總覽)

前言:疫情期間,在家辦公,雖說有種種不便,與此同時,也有了充足的時間,學習了一些想學習的知識,如有錯誤,敬請指出。

1:解讀

spring的主要功能是IOC與AOP,此章節暫時不講述AOP,但針對IOC來講,getBean()方法是重中之重,例如下面這個例子,我們這樣做就可以從容器中取出一個bean的實例

AnnotationConfigApplicationContext configApplicationContext=new AnnotationConfigApplicationContext(ProductServiceApplication.class);

configApplicationContext.getBean("test");

在整個spring源碼之中,new AnnotationConfigApplicationContext(ProductServiceApplication.class)可以說初始化方法佔據了極大的一部分,今天,不講述初始化的過程,單純從源碼角度講述getBean的工作流程

2:調用鏈說明

AnnotationConfigApplicationContext.getBean-->AbstractBeanFactory.getBean-->AbstractBeanFactory.doGetBean-->AbstractBeanFactory.getSingleton-->AbstractBeanFactory.createBean

上面是主要的流程,可以看出,getBean的真正獲取,是在BeanFactory裏面實現的,只不過AnnotationConfigContext裏面有bean工廠的實例,最終的bean的創建是在beanFactory裏面完成的

spring的方法命名規範也很有意思,幾個getBean的方法其實沒有做什麼事情,最終是在doGetBean和getSignleton與createBean裏面完成的。因此,代碼解析在doGetBean(AbstractBeanFactory)開始。(由於電腦原因,down下來的spring源碼已經丟了,只能看反編譯過的代碼,出入不大)

3:doGetBean解析

protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
        //獲取bean的名稱(因爲存在FactoryBean,以後的博客再講)
        final String beanName = this.transformedBeanName(name);
        //緩存,如果單例池中有的話就從單例池中獲取,沒有的話再創建,這個方法重要,解決循環依賴也是在這操作的
        Object sharedInstance = this.getSingleton(beanName);
        Object bean;
        if (sharedInstance != null && args == null) {
            //如果緩存池中存在
            if (this.logger.isDebugEnabled()) {
                if (this.isSingletonCurrentlyInCreation(beanName)) {
                    this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
                } else {
                    this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
                }
            }

            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        }
            if (!typeCheckOnly) {
                this.markBeanAsCreated(beanName);
            }

            try {
                final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
               
                //又是一個重要的代碼

                if (mbd.isSingleton()) {
                    sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
                        public Object getObject() throws BeansException {
                            try {
                                return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                            } catch (BeansException var2) {
                                AbstractBeanFactory.this.destroySingleton(beanName);
                                throw var2;
                            }
                        }
                    });
                    bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

           } 
    }

與流程無關的代碼已經被我刪減了,可以看這些重要的代碼。

(1):final String beanName = this.transformedBeanName(name);這主要是獲取bean的一個名稱,這麼解釋可能有些人有疑問了,不是我們getBean的時候已經把bean的名稱傳遞進來了麼,這麼做的原因是因爲存在一種特殊的bean(FactoryBean),之後會單開一講專門講解這個(很重要,一些三方框架例如mybatis與spring整合的時候就用到這個了)

(2):Object sharedInstance = this.getSingleton(beanName);主要是從單例池中獲取bean,因爲我們getBean獲取的事單例模式的,所以假設我們之前創建過的時候不會重複創建,直接在單例池中取出來返回,而且這也是spring解決循環依賴的重要部分(不懂什麼叫循環依賴的同學自行百度)

看下這塊的代碼邏輯

public Object getSingleton(String beanName) {
        return this.getSingleton(beanName, true);
    }

//參數allowEarlyReference的意思是是否允許提前創建,spring解決循環依賴就是通過允許提前創建一個實例來解決的

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        //singletonObjects單例池對象,存儲單例對象的一個map
        Object singletonObject = this.singletonObjects.get(beanName);
        
        //如果單例池中不存在&並且這個對象正在創建
        if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
            synchronized(this.singletonObjects) {
                //earlySingletonObjects(提前創建的bean的單例池)
                singletonObject = this.earlySingletonObjects.get(beanName);
                if (singletonObject == null && allowEarlyReference) {
                    ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        //還是空,beanFactory.getBean方法獲取
                        singletonObject = singletonFactory.getObject();
                        //放入提前創建的單例池中
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }

        return singletonObject != NULL_OBJECT ? singletonObject : null;
 }

getSignleton()方法的主要功能是看單例池中是否存在這個對象,存在返回,不存在則繼續進行(關於earlySingletonObjects與singletonFactory可以暫時不用關注,結合後面內容一起理解)

(3):getSignleton(String beanName,ObjectFactory objectFacorty)注意區別下上面的getSingle方法,這裏進入了BeanFactory真正創建單例對象的過程

sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
                        public Object getObject() throws BeansException {
                            try {
                                //這裏是獲取一個FactoryBean對象
                                return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                            } catch (BeansException var2) {
                                AbstractBeanFactory.this.destroySingleton(beanName);
                                throw var2;
                            }
                        }
                    });

這其中應用到了好多後置處理器的地方,暫時不進行講解,後面會抽時間吶出專門的篇章進行介紹後置處理器(Spring AOP功能就是利用後置處理器完成的)

進入getSignleton(beanName,FactoryBean factoryBean)方法內部

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "'beanName' must not be null");
        synchronized(this.singletonObjects) {
            //同樣,先從緩存池中獲取,沒有再創建
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                if (this.singletonsCurrentlyInDestruction) {
                    throw new BeanCreationNotAllowedException(beanName, "Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)");
                }

                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                //將這個beanName加入singletonsCurrentlyInCreation集合裏面(代表正在創建此對象)
                this.beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = this.suppressedExceptions == null;
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet();
                }

                try {
                    //調用剛剛說的自己創建的FactoryBean進行創建對象
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                } catch (IllegalStateException var16) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw var16;
                    }
                } catch (BeanCreationException var17) {
                    BeanCreationException ex = var17;
                    if (recordSuppressedExceptions) {
                        Iterator var8 = this.suppressedExceptions.iterator();

                        while(var8.hasNext()) {
                            Exception suppressedException = (Exception)var8.next();
                            ex.addRelatedCause(suppressedException);
                        }
                    }

                    throw ex;
                } finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    //不用關注,校驗

                    this.afterSingletonCreation(beanName);
                }

                if (newSingleton) {
                    //如果是第一次創建這個對象,需要把這個對象加入到singletonObjects單例池,並且從singletonFactories與earlySingletonObjects移除他,這兩個map的作用會在循環依賴中講到
                    this.addSingleton(beanName, singletonObject);
                }
            }

            return singletonObject != NULL_OBJECT ? singletonObject : null;
        }
    }

總結下getSignleton(beanName,FactoryBean factoryBean)方法

【1】:單例緩存池中沒有的話再創建

【2】:調用傳進來的FactoryBean的getBean方法獲取對象

【3】:創建末尾,將創建好的對象加入單例池,並且從singletonFactories與earlySinletonObjects中移除這個beanName。

重點關注【2】,我們在調用這個方法的時候自己創建了一個beanFactory並且,因此,創建的主要邏輯就在這裏面了

sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
                        public Object getObject() throws BeansException {
                            try {
                                //這裏是獲取一個FactoryBean對象--創建對象的主要邏輯了
                                return AbstractBeanFactory.this.createBean(beanName, mbd, args);
                            } catch (BeansException var2) {
                                AbstractBeanFactory.this.destroySingleton(beanName);
                                throw var2;
                            }
                        }
                    });

(4):AbstractBeanFactory.createBean(beanName,mbd,args)【不重要的代碼塊已刪除】

protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        
        RootBeanDefinition mbdToUse = mbd;
        Object beanInstance;
        try {
            //這裏本來想刪除來,但是這裏是實現代理的重要地方,利用後置處理器完成,暫時保留,但是不講解,在獲取bean的時候【沒有代理的時候】沒有用,可以忽略,等將後置處理器的時候再進行講解
            beanInstance = this.resolveBeforeInstantiation(beanName, mbdToUse);
            if (beanInstance != null) {
                return beanInstance;
            }
        } catch (Throwable var8) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var8);
        }
        //又是相似的命名邏輯,createBean-->doCreateBean,真正操作的邏輯都是在do開頭的方法裏面
        beanInstance = this.doCreateBean(beanName, mbdToUse, args);
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Finished creating instance of bean '" + beanName + "'");
        }

        return beanInstance;
    }

createBean裏面又調用了doCreateBean,真正的邏輯再doCreateBean裏面,方法命名形式眼熟不,(getSingleton-->doGetSingleton)

因此,我們到doCreateBean裏面看下真正的操作(這個方法很複雜+重要,spring的後置處理器在這裏體現的淋漓盡致)

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
        }
        //BeanWrapper 可以理解爲bean的包裝類,BeanWrapper我們可以獲取到bean
        if (instanceWrapper == null) {
            instanceWrapper = this.createBeanInstance(beanName, mbd, args);
        }

        final Object bean = instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null;
        Class<?> beanType = instanceWrapper != null ? instanceWrapper.getWrappedClass() : null;
        mbd.resolvedTargetType = beanType;
        synchronized(mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    //bean的後置處理器--暫時可以忽略
                    this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
                } catch (Throwable var17) {
                    throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
                }

                mbd.postProcessed = true;
            }
        }
        //判斷我們這個bean是否可以被提前創建-說白了就是可以不可以被循環依賴
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }
            //如果可以循環依賴的話就把bean加入到singletonfactory中,之後單獨拿出來寫一下如何解決的循環依賴
            this.addSingletonFactory(beanName, new ObjectFactory<Object>() {
                public Object getObject() throws BeansException {
                    return AbstractAutowireCapableBeanFactory.this.getEarlyBeanReference(beanName, mbd, bean);
                }
            });
        }

        Object exposedObject = bean;

        try {
            //屬性注入,也是利用後置處理器完成的【又是一塊很複雜且重要的代碼】
            this.populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                exposedObject = this.initializeBean(beanName, exposedObject, mbd);
            }
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }

            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
        }
        //這裏有代碼,不重要,已刪除

        try {
            this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
            return exposedObject;
        } catch (BeanDefinitionValidationException var16) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
        }
    }

4:結語

以上,就是spring getBean的源碼概覽,挖了很多坑,例如,spring是如何解決循環依賴的;spring後置處理器如何操作,在getBean的過程中如何在哪裏有應用後置處理器;spring如何進行屬性注入【其實也是利用後置處理器】;再進一步,spring aop是怎麼實現的【也是在getBean這個實現的】。接下來的一段時間,會慢慢把這些坑給填上的~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章