spring bean工廠和工廠bean 源碼分析

聊聊工廠bean和bean工廠有什么同異,先說結(jié)論

  • bean工廠:不是bean,在spring中一般指的是DefaultListableBeanFactory對(duì)象,管理和維護(hù)spring中所有的bean
  • 工廠bean:一種特殊的bean,在xml文件中配置的颤霎,用來生成新的bean的加工廠,通過getObject()方法可以獲取其生產(chǎn)的新bean,如果想獲取該工廠bean本身友酱,需要使用類似于getBean("&" + beanName)的樣式晴音。

demo

先來個(gè)小demo,具體學(xué)習(xí)和了解下如何使用工廠bean

public class StudentFactoryBean extends AbstractFactoryBean<Object> {

    @Override
    public Class<?> getObjectType() {
        return Student.class;
    }

    @Override
    protected Object createInstance() throws Exception {
        return new Student("factoryDemo", 18);
    }

    @Override
    public String toString() {
        return "StudentFactoryBean";
    }
}

public class Bootstrap {

    public static void main(String[] args){
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                new String[]{"context.xml"}, false);

        applicationContext.setAllowBeanDefinitionOverriding(false);
        applicationContext.refresh();

        Student student = (Student)applicationContext.getBean("studentFactory");
        // 生成工廠類生成的具體實(shí)體類缔杉,值的是studentFactory生成的類
        System.out.println(student.toString());

        StudentFactoryBean studentFactoryBean = (StudentFactoryBean) applicationContext.getBean("&studentFactory");
        // 名字加了一個(gè)& 獲取的是studentFactory本身
        System.out.println(studentFactoryBean.toString());
    }
}
<bean name="studentFactory" class="com.demo.StudentFactoryBean" />

如上述代碼所述锤躁,我們自定義繼承了AbstractFactoryBean抽象類,并實(shí)現(xiàn)了幾個(gè)方法或详,便于生成具體的Student類

image.png

執(zhí)行結(jié)果也如設(shè)想的一般系羞,分別打印各自對(duì)象的toString,不過className并沒有被自動(dòng)注解上

源碼分析

以前的學(xué)習(xí)我們已經(jīng)知道了在refresh已經(jīng)完成了對(duì)xml配置的bean的實(shí)例化操作了。如下圖當(dāng)還未執(zhí)行g(shù)etBean("studentFactory")操作時(shí)霸琴,studentFactory和對(duì)應(yīng)的實(shí)體類都已經(jīng)完成了實(shí)例化操作(這點(diǎn)是需要關(guān)注的點(diǎn))

image.png

接下來我們就在回過頭看看refresh的操作是如何完成實(shí)例化的椒振。

DefaultListableBeanFactory 文件

public void preInstantiateSingletons() throws BeansException {
    List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);

    // Trigger initialization of all non-lazy singleton beans...
    for (String beanName : beanNames) {
        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
        // 得到合并parentBean的beandefinition bd
        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
           // 不是抽象類 是單例類型同時(shí)不是懶加載的beandefinition
            if (isFactoryBean(beanName)) {
               // 如果是工廠bean(針對(duì)beanName對(duì)應(yīng)的class類型匹配判斷)
                final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
                // 調(diào)用getBean("&" + beanName)操作,返回的factory是工廠bean實(shí)例
                // 這樣在這個(gè)bean實(shí)例中梧乘,存儲(chǔ)著映射的具體bean
                boolean isEagerInit;
                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                    isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
                        @Override
                        public Boolean run() {
                            return ((SmartFactoryBean<?>) factory).isEagerInit();
                        }
                    }, getAccessControlContext());
                }
                else {
                    isEagerInit = (factory instanceof SmartFactoryBean &&
                            ((SmartFactoryBean<?>) factory).isEagerInit());
                }
                if (isEagerInit) {
                    getBean(beanName);
                }
            }
            else {
                getBean(beanName);
            }
        }
    }

    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
        Object singletonInstance = getSingleton(beanName);
        if (singletonInstance instanceof SmartInitializingSingleton) {
            final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
            if (System.getSecurityManager() != null) {
                AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    @Override
                    public Object run() {
                        smartSingleton.afterSingletonsInstantiated();
                        return null;
                    }
                }, getAccessControlContext());
            }
            else {
                smartSingleton.afterSingletonsInstantiated();
            }
        }
    }
}

AbstractBeanFactory 文件

protected <T> T doGetBean(
        final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
        throws BeansException {

    final String beanName = transformedBeanName(name);
    // 如果是"&" + beanName杠人,那么beanName就是去掉&的值
    Object bean;

    Object sharedInstance = getSingleton(beanName);
    // 從singletonObjects 中獲取已經(jīng)處理好的single 實(shí)例化對(duì)象
    if (sharedInstance != null && args == null) {
        // single已經(jīng)有數(shù)據(jù)了,而且參數(shù)也沒有宋下,生成真正的對(duì)象bean
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        if (isPrototypeCurrentlyInCreation(beanName)) {
           // 如果當(dāng)前的beanName在prototype的創(chuàng)建中,則拋出異常
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 獲取當(dāng)前bean工廠的父親工廠
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // 如果有父親工廠辑莫,而且還未處理
            String nameToLookup = originalBeanName(name);
            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);
            }
        }

        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        try {
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // 得到當(dāng)前beandefinition的依賴元素
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    registerDependentBean(dep, beanName);
                    getBean(dep);
                        // 把每一個(gè)必須依賴的bean注冊(cè)好学歧,并進(jìn)行實(shí)例化操作
                }
            }

            // 到這里就完成了一個(gè)對(duì)象實(shí)例化之前的操作了,現(xiàn)在需要?jiǎng)?chuàng)建具體的對(duì)象
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
                    @Override
                    public Object getObject() throws BeansException {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    }
                });
                // 得到的sharedInstance 是工廠類 StudentBeanFactory對(duì)象
                // 獲取真正的實(shí)例對(duì)象各吨,返回
                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 {
                String scopeName = mbd.getScope();
                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, 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 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);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
        try {
            return getTypeConverter().convertIfNecessary(bean, requiredType);
        }
        catch (TypeMismatchException ex) {
            if (logger.isDebugEnabled()) {
                logger.debug("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    // 強(qiáng)轉(zhuǎn)類型為T
    return (T) bean;
}

AbstractAutowireCapableBeanFactory 文件 真正創(chuàng)建對(duì)象的方法

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
        throws BeanCreationException {

    // Instantiate the bean.
    BeanWrapper instanceWrapper = null;
    if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    if (instanceWrapper == null) {
        instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
    Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
    mbd.resolvedTargetType = beanType;

    // 獲取到所有的MergedBeanDefinitionPostProcessor 對(duì)象枝笨,依次去修改對(duì)應(yīng)的bean信息
    // 這樣就可以再對(duì)BeanDefinition 進(jìn)行修改處理了
    // 而且!=已选横浑!自動(dòng)注入值就是在這里通過AutowiredAnnotationBeanPostProcessor類完成的
    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;
        }
    }

    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
            isSingletonCurrentlyInCreation(beanName));
    // 判斷是否是正在處理當(dāng)前這個(gè)single對(duì)象,而且允許循環(huán)引用
    if (earlySingletonExposure) {
        if (logger.isDebugEnabled()) {
            logger.debug("Eagerly caching bean '" + beanName +
                    "' to allow for resolving potential circular references");
        }
        addSingletonFactory(beanName, new ObjectFactory<Object>() {
            @Override
            public Object getObject() throws BeansException {
                return getEarlyBeanReference(beanName, mbd, bean);
            }
        });
    }

    // Initialize the bean instance.
    Object exposedObject = bean;
    try {
        populateBean(beanName, mbd, instanceWrapper);
        // 完成值的真正填充屉更,注意在上面說過使用AutowiredAnnotationBeanPostProcessor注入值徙融,其實(shí)并沒有注入絕對(duì)的值,而是注入的相關(guān)數(shù)據(jù)瑰谜,在populated的時(shí)候才是完成真正的值注入
        if (exposedObject != null) {
            exposedObject = initializeBean(beanName, exposedObject, mbd);
            // 這一步很關(guān)鍵欺冀,重點(diǎn)關(guān)注下面貼出來的invokeInitMethods 方法
        }
    }
    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);
        }
    }
   ....
    return exposedObject;
}

//   ======  分割線 ======

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
        throws Throwable {

    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
            try {
                AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                    @Override
                    public Object run() throws Exception {
                        ((InitializingBean) bean).afterPropertiesSet();
                        return null;
                    }
                }, getAccessControlContext());
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
           // 調(diào)用afterPropertiesSet 方法,完成對(duì)bean的singletonInstance實(shí)例化
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }
  ...
}

AbstractFactoryBean 文件

    public void afterPropertiesSet() throws Exception {
        if (isSingleton()) {
            this.initialized = true;
            this.singletonInstance = createInstance();
            // 相當(dāng)關(guān)鍵的一步H浴R!2吃纭职车!調(diào)用createInstance
            this.earlySingletonInstance = null;
        }
    }

如圖所示,在執(zhí)行initializeBean之前時(shí),完成了對(duì)象的實(shí)例化悴灵,還會(huì)繼續(xù)進(jìn)行初始化bean操作

image.png

執(zhí)行initializeBean 之后扛芽,已經(jīng)填充了singletonInstance 對(duì)象了,其包含的是工廠生成的bean數(shù)據(jù)

image.png

完成整個(gè)的refresh操作之后称勋,其實(shí)所有的未懶加載的bean都已經(jīng)完成的實(shí)例化胸哥,工廠bean對(duì)應(yīng)的具體bean也被保存在工廠bean中。

接下來講講在完成實(shí)例化之后赡鲜,調(diào)用getBean獲取工廠bean實(shí)例以及工廠bean本身的細(xì)節(jié)

  • getBean("studentFactory")
  • getBean("&studentFactory")

1空厌、老套路來到了doGetBean方法,得出name的原始beanName值
2、從singletonObjects找確認(rèn)存在該值
3银酬、進(jìn)入到getObjectForBeanInstance方法
4嘲更、如果想要返回的是工廠bean本身,而且還不為null揩瞪,直接返回(也就是getBean("&studentFactory")操作)
5赋朦、從factoryBeanObjectCache確認(rèn)是否存在對(duì)應(yīng)的值

如果有,意味著存在這個(gè)對(duì)應(yīng)的值李破,直接返回(也就是多次getBean("studentFactory")操作)
沒有宠哄,需要getObjectFromFactoryBean這個(gè)方法,往factoryBeanObjectCache填充新的實(shí)例

image.png

這里需要注意的是存儲(chǔ)的value是工廠bean關(guān)聯(lián)的真實(shí)bean直接返回(也就是首次執(zhí)行g(shù)etBean("studentFactory")操作)

不過最后還有個(gè)問題嗤攻,就是最后生成的該對(duì)象Student并沒有為className注入值,通過上面的實(shí)現(xiàn)毛嫉,壓根沒有自動(dòng)注解的那段操作,而是在自定義的工廠bean中通過createInstance方法返回的妇菱,所以肯定是沒有值的承粤。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市闯团,隨后出現(xiàn)的幾起案子辛臊,更是在濱河造成了極大的恐慌,老刑警劉巖房交,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彻舰,死亡現(xiàn)場離奇詭異,居然都是意外死亡候味,警方通過查閱死者的電腦和手機(jī)淹遵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來负溪,“玉大人透揣,你說我怎么就攤上這事〈眨” “怎么了辐真?”我有些...
    開封第一講書人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵须尚,是天一觀的道長。 經(jīng)常有香客問我侍咱,道長耐床,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任楔脯,我火速辦了婚禮撩轰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘昧廷。我一直安慰自己堪嫂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開白布木柬。 她就那樣靜靜地躺著皆串,像睡著了一般。 火紅的嫁衣襯著肌膚如雪眉枕。 梳的紋絲不亂的頭發(fā)上恶复,一...
    開封第一講書人閱讀 52,785評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音速挑,去河邊找鬼谤牡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛姥宝,可吹牛的內(nèi)容都是我干的拓哟。 我是一名探鬼主播,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼伶授,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了流纹?” 一聲冷哼從身側(cè)響起糜烹,我...
    開封第一講書人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎漱凝,沒想到半個(gè)月后疮蹦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡茸炒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年愕乎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壁公。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡感论,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出紊册,到底是詐尸還是另有隱情比肄,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站芳绩,受9級(jí)特大地震影響掀亥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜妥色,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一搪花、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嘹害,春花似錦撮竿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至凿可,卻和暖如春惑折,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背枯跑。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來泰國打工惨驶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人敛助。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓粗卜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親纳击。 傳聞我的和親對(duì)象是個(gè)殘疾皇子续扔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 寫在前面:我是直接通過閱讀Spring源碼并參考《Spring技術(shù)內(nèi)幕(第2版)》一書來對(duì)Spring核心設(shè)計(jì)思想...
    EakonZhao閱讀 3,215評(píng)論 2 12
  • 看到一篇好文章http://www.reibang.com/p/524748c83dde,所以自己也跟著走了一遍焕数。...
    lijiaccy閱讀 1,061評(píng)論 0 3
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理纱昧,服務(wù)發(fā)現(xiàn),斷路器堡赔,智...
    卡卡羅2017閱讀 134,717評(píng)論 18 139
  • Spring源碼解析——Bean的加載前奏 User user = (User)context.getBean("...
    仗劍詩篇閱讀 875評(píng)論 0 2
  • 我和他的故事發(fā)生在初三的那個(gè)夏日我班里和朋友聊天班主任走進(jìn)來你緊跟她善已,向大家介紹你的名字坐在我身邊跟我打招呼灼捂。 他...
    離落依閱讀 309評(píng)論 0 0