激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 詳解Spring 如何創(chuàng)建 Bean 對象?

詳解Spring 如何創(chuàng)建 Bean 對象?

2021-03-08 23:34WriteOnReadjaxer Java教程

本文在前文的基礎(chǔ)上又進(jìn)一步細(xì)化,主要從整體上探討了 Spring 如何創(chuàng)建單例的 bean 對象。

詳解Spring 如何創(chuàng)建 Bean 對象?

前情回顧前文「Spring 如何從 IoC 容器中獲取對象?」從整體上分析了如何從 Spring IoC 容器獲取一個 bean 對象。該邏輯由 AbstractBeanFactory#doGetBean 方法實現(xiàn),主要流程如下:

詳解Spring 如何創(chuàng)建 Bean 對象?

本文進(jìn)一步深入細(xì)節(jié),主要分析如何創(chuàng)建 singleton(單例)類型的對象。

如何創(chuàng)建單例對象?

從流程圖可以看出,當(dāng)獲取一個 bean 對象時,Spring 會首先嘗試從緩存中獲取單例對象。

值得注意是的:

  • 只有對象是單例的場景,即 scope 為 singleton 時才會緩存對象。
  • 這里其實涉及到了所謂的「三級緩存」,為了更容易理解三級緩存,本文先研究這個 bean 對象是什么時候放入緩存的,后面再研究三級緩存。

既然能取,必然有地方把 bean 對象存入了緩存,那緩存中的數(shù)據(jù)是從哪里來的呢?

下面主要分析單例對象是如何創(chuàng)建、并放入緩存中的。

該邏輯在 AbstractBeanFactory#doGetBean 方法中,主要代碼如下(保留了創(chuàng)建單例 bean 對象的代碼,其他部分暫時忽略):

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory { 

    // ... 

 

    protected <T> T doGetBean( 

            String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) 

            throws BeansException { 

 

        String beanName = transformedBeanName(name); 

        Object bean; 

 

        // 從緩存中獲取單例 bean 對象 

        Object sharedInstance = getSingleton(beanName); 

         

        // 緩存中不存在 bean 對象 

        else { 

 

            // ... 

 

            try { 

                // 獲取 BeanDefinition 

                RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 

 

                // 獲取依賴的 bean 對象 

                // 若創(chuàng)建一個 bean 對象時依賴其他對象,則先創(chuàng)建被依賴對象 

                // ... 

 

                // 創(chuàng)建 scope 為 singleton(單例)的對象 

                if (mbd.isSingleton()) { 

                    sharedInstance = getSingleton(beanName, () -> { 

                        try { 

                            return createBean(beanName, mbd, args); 

                        } 

                        catch (BeansException ex) { 

                            // ... 

                        } 

                    }); 

                    // 處理 FactoryBean 的場景 

                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 

                } 

 

                // 創(chuàng)建 scope 為 prototype 的對象 

                else if (mbd.isPrototype()) { 

                    // ... 

                } 

 

                // 創(chuàng)建其他類型對象 

                else { 

                    // ... 

                } 

            } 

            catch (BeansException ex) { 

                // ... 

            } 

        } 

 

        // 類型檢查 

 

        return (T) bean; 

    } 

其實就是這個 DefaultSingletonBeanRegistry#getSingleton 方法,代碼如下:

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { 

    // 單例 bean 對象緩存(beanName, bean) 

    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); 

 

    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { 

        Assert.notNull(beanName, "Bean name must not be null"); 

        synchronized (this.singletonObjects) { 

            // 先從緩存中獲取 bean 對象 

            Object singletonObject = this.singletonObjects.get(beanName); 

            // 緩存中不存在時再去創(chuàng)建 

            if (singletonObject == null) { 

                // ... 

                // 創(chuàng)建單例對象前 

                beforeSingletonCreation(beanName); 

                boolean newSingleton = false

                boolean recordSuppressedExceptions = (this.suppressedExceptions == null); 

                if (recordSuppressedExceptions) { 

                    this.suppressedExceptions = new LinkedHashSet<>(); 

                } 

                try { 

                    // 創(chuàng)建單例對象 

                    singletonObject = singletonFactory.getObject(); 

                    newSingleton = true

                } 

                // catch ... 

                finally { 

                    if (recordSuppressedExceptions) { 

                        this.suppressedExceptions = null

                    } 

                    // 創(chuàng)建單例對象后 

                    afterSingletonCreation(beanName); 

                } 

                if (newSingleton) { 

                    // 將對象添加到緩存 

                    addSingleton(beanName, singletonObject); 

                } 

            } 

            // 緩存中有的話直接返回 

            return singletonObject; 

        } 

    } 

 

getSingleton 方法會先從緩存 singletonObjects(其實就是一個 Map)中獲取 bean 對象,如果緩存有就直接返回,否則再去創(chuàng)建。創(chuàng)建成功后,會把該對象存入緩存。

創(chuàng)建的邏輯在哪呢?

看代碼是通過 ObjectFactory#getObject 方法來創(chuàng)建的,ObjectFactory 是一個函數(shù)式接口:

@FunctionalInterface 

public interface ObjectFactory<T> { 

    T getObject() throws BeansException; 

這個方法的實現(xiàn)是什么呢?退回上一層,即 getBean 方法,看這里:

sharedInstance = getSingleton(beanName, () -> { 

    try { 

        // 創(chuàng)建 bean 對象 

        return createBean(beanName, mbd, args); 

    } 

    catch (BeansException ex) { 

        // ... 

    } 

}); 

這里用到了 Lambda 表達(dá)式,將如下表達(dá)式作為參數(shù):

() -> { 

    try { 

        // 創(chuàng)建 bean 對象 

        return createBean(beanName, mbd, args); 

    } 

    catch (BeansException ex) { 

        // ... 

    } 

創(chuàng)建 bean 對象的邏輯就在這個 createBean 方法中,它在 AbstractAutowireCapableBeanFactory 類中:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory 

        implements AutowireCapableBeanFactory { 

 

    @Override 

    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 

            throws BeanCreationException { 

 

        RootBeanDefinition mbdToUse = mbd; 

 

        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 ... 

 

        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 ... 

 

        try { 

            // 創(chuàng)建 bean 對象 

            Object beanInstance = doCreateBean(beanName, mbdToUse, args); 

            if (logger.isTraceEnabled()) { 

                logger.trace("Finished creating instance of bean '" + beanName + "'"); 

            } 

            return beanInstance; 

        } 

        // catch ... 

    } 

  • 值得注意的是,resolveBeforeInstantiation 方法其實是跟 AOP 實現(xiàn)相關(guān)的,可能在這里生成代理對象就返回了。由于現(xiàn)在主要分析 IoC 的流程,因此這里暫時略過,有興趣的朋友們可以自行研究。

這里繼續(xù)沿著主線邏輯走。

創(chuàng)建 bean 對象是在 doCreateBean 方法中實現(xiàn)的,如下:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory 

        implements AutowireCapableBeanFactory { 

 

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 

            throws BeanCreationException { 

 

        // Instantiate the bean. 

        // 1. 實例化 bean 

        BeanWrapper instanceWrapper = null

        if (mbd.isSingleton()) { 

            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); 

        } 

        if (instanceWrapper == null) { 

            instanceWrapper = createBeanInstance(beanName, mbd, args); 

        } 

        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 ... 

                mbd.postProcessed = true

            } 

        } 

 

        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && 

                isSingletonCurrentlyInCreation(beanName)); 

        if (earlySingletonExposure) { 

            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); 

        } 

 

        // Initialize the bean instance. 

        Object exposedObject = bean; 

        try { 

            // 2. 填充屬性 

            populateBean(beanName, mbd, instanceWrapper); 

            // 3. 初始化 

            exposedObject = initializeBean(beanName, exposedObject, mbd); 

        } 

        // catch ... 

 

        if (earlySingletonExposure) { 

            Object earlySingletonReference = getSingleton(beanName, false); 

            if (earlySingletonReference != null) { 

                if (exposedObject == bean) { 

                    exposedObject = earlySingletonReference; 

                } 

                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { 

                    String[] dependentBeans = getDependentBeans(beanName); 

                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); 

                    for (String dependentBean : dependentBeans) { 

                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { 

                            actualDependentBeans.add(dependentBean); 

                        } 

                    } 

                    // ... 

                } 

            } 

        } 

 

        // Register bean as disposable. 

        try { 

            registerDisposableBeanIfNecessary(beanName, bean, mbd); 

        } 

        // catch ... 

 

        return exposedObject; 

    } 

 

  • 注意:Instantiate 和 Initialize 雖然看起來有點(diǎn)像,但它倆不是一回事,前者是“實例化”,后者是“初始化”。

這個方法看起來有點(diǎn)長,但最主要的事情只有三件:

  1. 創(chuàng)建 bean 對象:createBeanInstance 方法
  2. 填充屬性:populateBean 方法
  3. 初始化 bean:initializeBean 方法

這幾個方法內(nèi)部其實都有一大堆堆堆堆堆……的代碼,再對照一下前面給出的整體流程圖 :

詳解Spring 如何創(chuàng)建 Bean 對象?

就是這樣。

本文在前文整體分析的基礎(chǔ)上又進(jìn)一步細(xì)化,先到這里吧,后面再繼續(xù)分析~

小結(jié)

如何從 Spring IoC 容器中獲取 bean 對象?前文對此進(jìn)行了整體流程的分析。

本文在前文的基礎(chǔ)上又進(jìn)一步細(xì)化,主要從整體上探討了 Spring 如何創(chuàng)建單例的 bean 對象,整體上分為三個步驟:

  1. 創(chuàng)建 bean 對象。
  2. 填充 bean 屬性
  3. 初始化 bean 對象

至于這三個步驟具體又做了什么,且聽下回分解。

原文地址:https://mp.weixin.qq.com/s/8YxzDPTAHm5RagI8mX1L7Q

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产日本在线播放 | 男女污视频在线观看 | 黄色的视频免费看 | 欧美精品国产综合久久 | 黄色片免费看网站 | 主人在调教室性调教女仆游戏 | 91成人久久 | 免费的性生活视频 | 国产www免费| 二区三区四区视频 | 成人在线视频在线观看 | 国产精品www | 精品久久久久久久久久 | 日韩毛片免费观看 | 久久亚洲网 | 日韩在线视频免费观看 | 日本在线视频一区二区三区 | 久久精品成人免费国产片桃视频 | 污片在线观看视频 | 精品久久久久久综合日本 | 国产男女爽爽爽爽爽免费视频 | 久久免费视频一区二区三区 | 午夜久久电影 | 91精品国产一区二区三区四区在线 | 欧美一级毛片免费观看视频 | 日韩精品a在线观看 | 久久不射电影网 | 国产精品18久久久久久久 | 日韩视频一区二区三区在线观看 | 成人乱码一区二区三区不卡视频 | 一级黄色在线观看 | 国产精品美女久久久久久不卡 | 97精品国产高清在线看入口 | 日韩毛片毛片久久精品 | 日本不卡二区 | 欧美 videos粗暴 | 国产精品久久久久网站 | 国产一有一级毛片视频 | 午夜视频中文字幕 | 国产高清自拍一区 | www深夜成人 |