1. 程式人生 > 實用技巧 >spring ioc 原始碼分析(三)--finishBeanFactoryInitialization(beanFactory)

spring ioc 原始碼分析(三)--finishBeanFactoryInitialization(beanFactory)

之前的部落格專門分析了一個類到BeanDefinition的建立過程,現在分析BeanDefinition 到一個bean的建立過程:從refresh() 方法的---->finishBeanFactoryInitialization(beanFactory) 開始:

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        // 像容器中設定一個型別轉換器
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.
class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } //設定一個佔位符解析器 if (!beanFactory.hasEmbeddedValueResolver()) { beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal)); }
// loadTimeWeaver是用於類載入階段做切入使用的 String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null); // 凍結beanDefinition資訊,也就是下面要開始建立物件了,所以不允許再改變了 beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons. //開始例項化所有的單例bean beanFactory.preInstantiateSingletons(); }

小結:該方法主要是在單例bean開始初始化前,對beanFactory設定一些初始化資訊,最重要的還是: beanFactory.preInstantiateSingletons();

public void preInstantiateSingletons() throws BeansException {
       List<String> beanNames = new ArrayList<>(this.beanDefinitionNames); //獲取所有的beanNams 然後遍歷每個beanName,獲取其BeanDefintion,然後一個個的建立例項

        // Trigger initialization of all non-lazy singleton beans...
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName); //這裡為何是獲取MergeBeanDefinition呢,原因是在xml時代,一個bean 可以通過繼承一個抽象的bean,來獲得初始化的屬性
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) { //在這裡的beanDefinition必須不是抽象的,並且是單例,非懶載入的
                if (isFactoryBean(beanName)) { //如果是FactoryBean,通過get(BeanName)方式獲取的是裡面的getObject()返回的物件,如果是get("&beanName")的方式,就是獲取到FactoryBean本身
                    Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);//get("&beanName")方式,獲取到FactoryBean本身
                    if (bean instanceof FactoryBean) {
                        final FactoryBean<?> factory = (FactoryBean<?>) bean;
                        boolean isEagerInit;
                        if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                            isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                            ((SmartFactoryBean<?>) factory)::isEagerInit,
                                    getAccessControlContext());
                        }
                        else {
                            isEagerInit = (factory instanceof SmartFactoryBean &&
                                    ((SmartFactoryBean<?>) factory).isEagerInit());
                        }
                        if (isEagerInit) { //這裡的意思是,是否要那麼早初始化FactoryBean裡面的getObject()物件,預設是用到時才會初始化
                            getBean(beanName);//這裡呼叫的是FactoryBean裡面的getObject()
                        }
                    }
                }
                else {
                    getBean(beanName);//非factoryBean就開始建立物件,factoryBean 也是呼叫該方法建立物件,只是beanName不一樣getBean(FACTORY_BEAN_PREFIX + beanName)
                }
            }
        }

        // Trigger post-initialization callback for all applicable beans...
        for (String beanName : beanNames) { //至此,所有的例項物件都建立完畢,對於實現SmartInitializingSingleton的bean,在這裡會統一呼叫afterSingletonsInstantiated()
            Object singletonInstance = getSingleton(beanName);
            if (singletonInstance instanceof SmartInitializingSingleton) {
                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
                if (System.getSecurityManager() != null) {
                    AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }, getAccessControlContext());
                }
                else {
                    smartSingleton.afterSingletonsInstantiated();
                }
            }
        }
    }

小結:上面方法主要邏輯是:遍歷所有的bean的定義資訊,然後分別建立例項,這裡區分了FactoryBean和普通Bean的建立過程,所有Bean都建立完畢後,會對實現SmartInitializingSingleton介面的bean,呼叫afterSingletonsInstantiated()

//接下來我們分析下單個bean的建立過程:getBean(beanName)

//下面引數的意思: name或者requiredType的意思是通過名稱還是通過型別獲取物件,args的意思是,如果是通過有參構造器去建立的bean,需要該實參,typeCheckOnly的意思是,我只是想獲取返回的型別而不是物件,例如我想知道某個beanName的型別
//一般typeCheck是用於FactoryBean校驗裡面的getObject()返回的型別
protected
<T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { final String beanName = transformedBeanName(name);//這裡的意思的,在xml時代,一個bean可以擁有多個別名,如果你是通過別名來建立物件的話,這裡就會轉成對應的BeanName,因為BeanName才是唯一的 Object bean; // Eagerly check singleton cache for manually registered singletons. Object sharedInstance = getSingleton(beanName);//校驗例項物件是否已經存在了,這裡有三級快取,解決迴圈依賴的核心也在這裡,後續會分析該方法 if (sharedInstance != null && args == null) { if (logger.isTraceEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) {//判斷singletonsCurrentlyInCreation集合有沒有該bean,有就代表正在建立中 logger.trace("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.trace("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);//這裡的意思是:既然bean已經建立了,如果是FactoryBean,那麼這裡就要返回FactoryBean裡面的Object物件,其他的Bean直接返回 } else { //該方法只有非單例才會出現,這裡是判斷prototypesCurrentlyInCreation有沒包含該BeanName,prototypesCurrentlyInCreation是一個ThreadLocal,所以存在代表建立了2次 // We're assumably within a circular reference. if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // Check if bean definition exists in this factory. BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { //這裡面的邏輯是,如果BeanFactory並沒有包含該Bean的定義資訊,那麼久去找其父類,看看父類有沒該bean // Not found -> check parent. //查詢父類看看有沒該Bean String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { // Delegation to parent with explicit args. //使用有參構造器去建立例項 return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { // No args -> delegate to standard getBean method. return parentBeanFactory.getBean(nameToLookup, requiredType);//通過型別去建立例項 } else { return (T) parentBeanFactory.getBean(nameToLookup);//通過名稱去建立例項 } } if (!typeCheckOnly) { markBeanAsCreated(beanName); //這裡的意思是,本次呼叫方法,並非是要獲取bean的型別,而是為了建立例項,將beanName存到alreadyCreated集合,代表該bean已經建立了,後面try。。catch有異常會清空該beanName } try { final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);//mergeBeanDefinition的作用是解決xml時代,bean繼承一個抽象bean,獲取其對應屬性,類之間並非真的是繼承關係 checkMergedBeanDefinition(mbd, beanName, args);//這裡檢查mbd是否是抽象的,抽象的話就不能建立 // Guarantee initialization of beans that the current bean depends on. String[] dependsOn = mbd.getDependsOn(); //這裡是解決@DependsOn("xx")註解的作用,該註解的作用是,建立某個Bean前,必須先建立xx,xx可以是個陣列 if (dependsOn != null) { for (String dep : dependsOn) { if (isDependent(beanName, dep)) { //判斷是否相互之間有依賴關係,這個要結合下面程式碼registerDependentBean(dep, beanName);才好理解 throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } registerDependentBean(dep, beanName); try { getBean(dep); //先建立依賴的Bean } catch (NoSuchBeanDefinitionException ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", ex); } } } // Create bean instance. if (mbd.isSingleton()) { //如果是單例,就通過呼叫該方法建立 sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } 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);//這裡的意思前面也分析過了,意思是,如果是FactroyBean,就呼叫其getObject()方法,返回對應的物件 } else if (mbd.isPrototype()) { //如果是非單例 // It's a prototype -> create a new instance. Object prototypeInstance = null; try { beforePrototypeCreation(beanName);//存到prototypesCurrentlyInCreation這個ThreadLocal中,代表正在建立 prototypeInstance = createBean(beanName, mbd, args);//該方法跟單例建立例項呼叫的邏輯是一樣的,後續會分析 } finally { afterPrototypeCreation(beanName);//既然建立完畢,那麼久可以從ThreadLocal中移除該bean了 } bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);//這裡邏輯前面分析過了 } else { String scopeName = mbd.getScope(); //@Scope標註的bean 下面的邏輯跟建立非單例(原型protoType)bean一樣 final Scope scope = this.scopes.get(scopeName); if (scope == null) { throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'"); } try { Object scopedInstance = scope.get(beanName, () -> { beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args); } finally { afterPrototypeCreation(beanName); } }); bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd); } catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider " + "defining a scoped proxy for this bean if you intend to refer to it from a singleton", ex); } } } catch (BeansException ex) { cleanupAfterBeanCreationFailure(beanName);//前面做了markBeanAsCreated(beanName)代表該bean已經建立,失敗後,這裡就要刪除 throw ex; } } // Check if required type matches the type of the actual bean instance. if (requiredType != null && !requiredType.isInstance(bean)) { //如果我們需要的型別跟獲取的不一致,那麼就要轉換 try { T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType); if (convertedBean == null) { throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } return convertedBean; } catch (TypeMismatchException ex) { if (logger.isTraceEnabled()) { logger.trace("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", ex); } throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass()); } } return (T) bean; }

//小結:上面主要對不同的bean型別做了不同的操作,同時對依賴關係的bean也做了處理,這裡有2個方法,非常重要,一個是Object sharedInstance = getSingleton(beanName);該方法後續還會出現多次,

另一個是:createBean(beanName, mbd, args);我們先來看看第一個方法:Object sharedInstance = getSingleton(beanName);

    //該方法可以解決迴圈依賴,也就是A和B相互依賴,例如使用@autowried註解
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {//allowEarlyReference代表是否允許迴圈依賴
        Object singletonObject = this.singletonObjects.get(beanName);//我們建立的單例bean都會存在該Map中,如果已經建立,那麼久可以獲取到,我們可以把它看作一級快取
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//當一個Bean正在建立中此時已經new出來目標物件了,只是還沒有經過後置處理器處理,所以此時它是正在建立中,A依賴B,然後建立B,發現B依賴A,那麼久會建立A,建立A時,發現A已經正在建立了
synchronized (this.singletonObjects) { singletonObject = this.earlySingletonObjects.get(beanName); //先從二級快取獲取 if (singletonObject == null && allowEarlyReference) {//獲取不到 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName); //再從三級快取獲取,該快取是一個單例工廠 if (singletonFactory != null) { singletonObject = singletonFactory.getObject();//工廠中獲取物件 this.earlySingletonObjects.put(beanName, singletonObject);//存入二級快取 this.singletonFactories.remove(beanName);//移除工廠 那麼問題:為何要有二三級快取?原因是工廠裡面的方法可能會很複雜,所以工廠獲取物件後,存到二級快取中,下次再次獲取就更高效率了 } } } } return singletonObject; }