spring 源碼之 Bean 的加載(一)

直接切入正題,搞懂 Bean 的加載 spring 源碼就差不多了,萬(wàn)卷不離其宗。

AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(XXX.class);
         app.getBean(YYY.class);

直接通過(guò) AnnotationConfigApplicationContext 就到達(dá)入口。這個(gè) app 可以 get bean 所以 bean 在第一行就創(chuàng)建好了。

    public AnnotationConfigApplicationContext(Class... annotatedClasses) {
        this();
        this.register(annotatedClasses);
        this.refresh();
    }

refresh()
這個(gè)就是整個(gè)Spring Bean加載的核心了,它是ClassPathXmlApplicationContext的父類AbstractApplicationContext的一個(gè)方法,顧名思義,用于刷新整個(gè)Spring上下文信息,定義了整個(gè)Spring上下文加載的流程。

public void refresh() throws BeansException, IllegalStateException {
        // 對(duì)象鎖
        synchronized(this.startupShutdownMonitor) {
            //準(zhǔn)備刷新上下文 (設(shè)置激活標(biāo)志位)
            this.prepareRefresh();
            //獲取刷新Spring上下文的Bean工廠
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            //準(zhǔn)備 bean 工廠
            this.prepareBeanFactory(beanFactory);

            try {
                //允許 beanFactory 的 后置處理器
                this.postProcessBeanFactory(beanFactory);
                //調(diào)用工廠處理器注冊(cè)bean
                this.invokeBeanFactoryPostProcessors(beanFactory);
                //注冊(cè) bean 后置處理器
                this.registerBeanPostProcessors(beanFactory);
                //初始消息資源
                this.initMessageSource();
                //初始 event 多路廣播
                this.initApplicationEventMulticaster();
                //初始一些特殊的 bean
                this.onRefresh();
                //注冊(cè)監(jiān)聽(tīng)器
                this.registerListeners();
                // 這里完成bean 的初始化(非懶加載)
                this.finishBeanFactoryInitialization(beanFactory);  
                // 發(fā)布相關(guān)事件
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }
                //刪除 bean
                this.destroyBeans();
                //取消 refresh
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                // reset 激活標(biāo)志位
                this.resetCommonCaches();
            }

        }
    }

1、方法是加鎖的,這么做的原因是避免多線程同時(shí)刷新Spring上下文。

2、盡管加鎖可以看到是針對(duì)整個(gè)方法體的,但是沒(méi)有在方法前加 synchronized 關(guān)鍵字,而使用了對(duì)象鎖 startUpShutdownMonitor,這樣做有兩個(gè)好處:

(1)refresh()方法和close()方法都使用了 startUpShutdownMonitor 對(duì)象鎖加鎖,這就保證了在調(diào)用 refresh() 方法的時(shí)候無(wú)法調(diào)用 close() 方法,反之亦然,避免了沖突。

(2)另外一個(gè)好處不在這個(gè)方法中體現(xiàn),但是提一下,使用對(duì)象鎖可以減小了同步的范圍,只對(duì)不能并發(fā)的代碼塊進(jìn)行加鎖,提高了整體代碼運(yùn)行的效率。

finishBeanFactoryInitialization(beanFactory) 主要完成 bean 的加載。

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
            beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
        }

        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(new StringValueResolver() {
                public String resolveStringValue(String strVal) {
                    return AbstractApplicationContext.this.getEnvironment().resolvePlaceholders(strVal);
                }
            });
        }

        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        String[] var3 = weaverAwareNames;
        int var4 = weaverAwareNames.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            String weaverAwareName = var3[var5];
            this.getBean(weaverAwareName);
        }

        beanFactory.setTempClassLoader((ClassLoader)null);
        beanFactory.freezeConfiguration();
        beanFactory.preInstantiateSingletons();
    }

preInstantiateSingletons 方法是初始化單例 bean 的方法:

    public void preInstantiateSingletons() throws BeansException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Pre-instantiating singletons in " + this);
        }

        List<String> beanNames = new ArrayList(this.beanDefinitionNames);
        Iterator var2 = beanNames.iterator();

        while(true) {
            while(true) {
                String beanName;
                RootBeanDefinition bd;
                do {
                    do {
                        do {
                            if (!var2.hasNext()) {
                                var2 = beanNames.iterator();

                                while(var2.hasNext()) {
                                    beanName = (String)var2.next();
                                    Object singletonInstance = this.getSingleton(beanName);
                                    if (singletonInstance instanceof SmartInitializingSingleton) {
                                        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton)singletonInstance;
                                        if (System.getSecurityManager() != null) {
                                            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                                                public Object run() {
                                                    smartSingleton.afterSingletonsInstantiated();
                                                    return null;
                                                }
                                            }, this.getAccessControlContext());
                                        } else {
                                            smartSingleton.afterSingletonsInstantiated();
                                        }
                                    }
                                }

                                return;
                            }

                            beanName = (String)var2.next();
                            bd = this.getMergedLocalBeanDefinition(beanName);
                        } while(bd.isAbstract());
                    } while(!bd.isSingleton());
                } while(bd.isLazyInit());

                if (this.isFactoryBean(beanName)) {
                    final FactoryBean<?> factory = (FactoryBean)this.getBean("&" + beanName);
                    boolean isEagerInit;
                    if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                        isEagerInit = (Boolean)AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                            public Boolean run() {
                                return ((SmartFactoryBean)factory).isEagerInit();
                            }
                        }, this.getAccessControlContext());
                    } else {
                        isEagerInit = factory instanceof SmartFactoryBean && ((SmartFactoryBean)factory).isEagerInit();
                    }

                    if (isEagerInit) {
                        this.getBean(beanName);
                    }
                } else {
                    this.getBean(beanName);
                }
            }
        }
    }

這里先解釋一下getMergedLocalBeanDefinition方法的含義,因?yàn)檫@個(gè)方法會(huì)常常看到。Bean定義公共的抽象類是AbstractBeanDefinition,普通的Bean在Spring加載Bean定義的時(shí)候,實(shí)例化出來(lái)的是GenericBeanDefinition,而Spring上下文包括實(shí)例化所有Bean用的AbstractBeanDefinition是RootBeanDefinition,這時(shí)候就使用getMergedLocalBeanDefinition方法做了一次轉(zhuǎn)化,將非RootBeanDefinition轉(zhuǎn)換為RootBeanDefinition以供后續(xù)操作。

第1行~第10行的代碼是根據(jù)beanName拿到RootBeanDefinition。由于此方法實(shí)例化的是所有非懶加載的單例Bean,因此要實(shí)例化Bean,必須滿足11行的三個(gè)定義:

(1)不是抽象的

(2)必須是單例的

(3)必須是非懶加載的

接著簡(jiǎn)單看一下第12行~第29行的代碼,這段代碼主要做的是一件事情:首先判斷一下Bean是否FactoryBean的實(shí)現(xiàn),接著判斷Bean是否SmartFactoryBean的實(shí)現(xiàn),假如Bean是SmartFactoryBean的實(shí)現(xiàn)并且eagerInit(這個(gè)單詞字面意思是渴望加載,找不到一個(gè)好的詞語(yǔ)去翻譯,意思就是定義了這個(gè)Bean需要立即加載的意思)的話,會(huì)立即實(shí)例化這個(gè)Bean。Java開(kāi)發(fā)人員不需要關(guān)注這段代碼,因?yàn)镾martFactoryBean基本不會(huì)用到,我翻譯一下Spring官網(wǎng)對(duì)于SmartFactoryBean的定義描述:

-FactoryBean接口的擴(kuò)展接口。接口實(shí)現(xiàn)并不表示是否總是返回單獨(dú)的實(shí)例對(duì)象,比如FactoryBean.isSingleton()實(shí)現(xiàn)返回false的情況并不清晰地表示每次返回的都是單獨(dú)的實(shí)例對(duì)象。

-不實(shí)現(xiàn)這個(gè)擴(kuò)展接口的簡(jiǎn)單FactoryBean的實(shí)現(xiàn),F(xiàn)actoryBean.isSingleton()實(shí)現(xiàn)返回false總是簡(jiǎn)單地告訴我們每次返回的都是單獨(dú)的實(shí)例對(duì)象,暴露出來(lái)的對(duì)象只能夠通過(guò)命令訪問(wèn)。

-注意:這個(gè)接口是一個(gè)有特殊用途的接口,主要用于框架內(nèi)部使用與Spring相關(guān)。通常,應(yīng)用提供的FactoryBean接口實(shí)現(xiàn)應(yīng)當(dāng)只需要實(shí)現(xiàn)簡(jiǎn)單的FactoryBean接口即可,新方法應(yīng)當(dāng)加入到擴(kuò)展接口中去

獲取Bean對(duì)象實(shí)例,都是通過(guò)getBean方法,跟進(jìn)去看 doGetBean 方法。真正干事兒的基本上都是 do 開(kāi)頭的方法。

protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
        '//提取對(duì)應(yīng)的 beanName'
        final String beanName = this.transformedBeanName(name);
        '// 檢查緩存中或者實(shí)例工廠中是否有對(duì)應(yīng)的實(shí)例
        // 這里是為了解決單例 bean 下的循環(huán)依賴 
        //spring 創(chuàng)建 bean 的原則是不等 bean 創(chuàng)建完就將 創(chuàng)建 bean 的 ObjectFactory 提早曝光。
        //也就是將 ObjectFactory 加入到緩存中'
        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 + "'");
                }
            }
            '// 返回對(duì)應(yīng)的實(shí)例,有時(shí)候存在諸如 BeanFactory 的情況并不是直接返回實(shí)例本身而是返回指定方法返回的實(shí)例(這里應(yīng)該是用了代理)'
            bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
        } else {
            '// 只有單例情況下才會(huì)解決循環(huán)依賴'
            if (this.isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            BeanFactory parentBeanFactory = this.getParentBeanFactory();
           ' // 如果 beanDefinitionMap 中也就是在所有已經(jīng)加載的類中不包括 beanName 則嘗試從 parentBeanFactory 中檢測(cè)'
            if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
                String nameToLookup = this.originalBeanName(name);
                '// 遞歸到 BeanFactory 中尋找'
                if (args != null) {
                    return parentBeanFactory.getBean(nameToLookup, args);
                }

                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            '// 如果不是僅僅做類型檢查則是創(chuàng)建 bean 這里要記錄'
            if (!typeCheckOnly) {
                this.markBeanAsCreated(beanName);
            }

            try {
                '// 將存儲(chǔ) XML 配置文件的 GernericBeanDefiniton 轉(zhuǎn)換為 RootBeanDefinitionm, 如果指定 BeanName 是子 Bean 的同時(shí)會(huì)合并父類的相關(guān)屬性'
                final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
                this.checkMergedBeanDefinition(mbd, beanName, args);
                String[] dependsOn = mbd.getDependsOn();
                String[] var11;
                '// 若存在依賴則需要遞歸實(shí)例化依賴的 bean'
                if (dependsOn != null) {
                    var11 = dependsOn;
                    int var12 = dependsOn.length;
                    
                    for(int var13 = 0; var13 < var12; ++var13) {
                        String dep = var11[var13];
                        if (this.isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        '// 緩存依賴調(diào)用'
                        this.registerDependentBean(dep, beanName);

                        try {
                            this.getBean(dep);
                        } catch (NoSuchBeanDefinitionException var24) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
                        }
                    }
                }
                '// 實(shí)例化依賴的 bean 后便可以實(shí)例化 mbd本身了'
                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);
                '// 原型模式的創(chuàng)建'
                } else if (mbd.isPrototype()) {
                    var11 = null;

                    Object prototypeInstance;
                    try {
                        this.beforePrototypeCreation(beanName);
                        prototypeInstance = this.createBean(beanName, mbd, args);
                    } finally {
                        this.afterPrototypeCreation(beanName);
                    }

                    bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                } else {
                    '// 指定的 scope 上實(shí)例化 bean'
                    String scopeName = mbd.getScope();
                    Scope 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, new ObjectFactory<Object>() {
                            public Object getObject() throws BeansException {
                                AbstractBeanFactory.this.beforePrototypeCreation(beanName);

                                Object var1;
                                try {
                                    var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args);
                                } finally {
                                    AbstractBeanFactory.this.afterPrototypeCreation(beanName);
                                }

                                return var1;
                            }
                        });
                        bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException var23) {
                        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", var23);
                    }
                }
            } catch (BeansException var26) {
                this.cleanupAfterBeanCreationFailure(beanName);
                throw var26;
            }
        }
        '// 檢查需要的類型是否符合 bean 的實(shí)際類型'
        if (requiredType != null && bean != null && !requiredType.isInstance(bean)) {
            try {
                return this.getTypeConverter().convertIfNecessary(bean, requiredType);
            } catch (TypeMismatchException var25) {
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var25);
                }

                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        } else {
            return bean;
        }
    }

加載過(guò)程中所涉及的步驟如下:
1.轉(zhuǎn)換對(duì)應(yīng) beanName
這里傳入的參數(shù)可能是別名,也可能是 FactoryBean,所以需要進(jìn)行一系列的解析。
-去除 FactoryBean 的修飾符,如果 name 是 “&aa”,那么去除 & 使 name 為 “aa”。
-去指定的 alias 所表示的最終 beanName,例如別名 A 指向名稱為 B 的 bean 則返回 B。

2.嘗試從緩存中加載單例
單例在 Spring 的同一容器內(nèi)只會(huì)被創(chuàng)建一次,后續(xù)再獲取 bean,就直接從單例緩存中獲取了。這里只是嘗試加載,首先嘗試從緩存中加載,如果加載不成功則再次嘗試從 singletonFactories 中加載。為了避免循環(huán)依賴,Spring 的原則是不等 bean 創(chuàng)建完成就會(huì)將創(chuàng)建 bean 的 ObjectFactory 提早曝光加入到緩存中。

  1. bean 的實(shí)例化
    如果從緩存中得到了 bean 的原始狀態(tài),則需要對(duì) bean 進(jìn)行實(shí)例化。緩存中只是最原始的 bean 狀態(tài),并不一定是想要的。假如我們要對(duì)工廠 bean 進(jìn)行處理,這里其實(shí)是工廠 bean 的初始狀態(tài),但是我們真正需要的是工廠 bean 中定義的 factory-method 方法中返回的 bean,而 getObjectForBeanInstance 就是完成這個(gè)工作的。

4.原型模式的依賴檢查
只有單例情況下才會(huì)嘗試解決循環(huán)依賴,原型模式下只會(huì)拋出異常

5.檢測(cè) parentBeanFactory
parentBeanFactory != null && !this.containsBeanDefinition(beanName) 加載的 XML 配置文件中不包含 beanName 所對(duì)應(yīng)的配置 就只能到 parentBeanFactory 去嘗試下了,然后再去遞歸的調(diào)用 getBean 方法。

6.將存儲(chǔ) XML 配置文件的 GernericBeanDefinition 轉(zhuǎn)換為 RootBeanDefinition

7.尋找依賴
bean 初始化過(guò)程中很可能用到某些屬性,而某些屬性可能是動(dòng)態(tài)配置的,并且配置成依賴于其他的 bean, 那么這個(gè)時(shí)候就有必要先加載依賴的 bean,所以,在 spring 加載循序中,在初始化 bean 的時(shí)候會(huì)首先初始化這個(gè) bean 所對(duì)應(yīng)的依賴。

8.針對(duì)不用的 scope 進(jìn)行 bean 的創(chuàng)建。
singleton prototype request 等。

9.類型轉(zhuǎn)換
將返回的 bean 轉(zhuǎn)換為 requiredType 所指定的類型。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容