您好,登錄后才能下訂單哦!
這篇文章主要講解了“Spring 如何創建 Bean 對象”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Spring 如何創建 Bean 對象”吧!
從整體上分析了如何從 Spring IoC 容器獲取一個 bean 對象。該邏輯由 AbstractBeanFactory#doGetBean 方法實現,主要流程如下:
本文進一步深入細節,主要分析如何創建 singleton(單例)類型的對象。
如何創建單例對象?
從流程圖可以看出,當獲取一個 bean 對象時,Spring 會首先嘗試從緩存中獲取單例對象。
值得注意是的:
鴻蒙官方戰略合作共建——HarmonyOS技術社區
只有對象是單例的場景,即 scope 為 singleton 時才會緩存對象。
這里其實涉及到了所謂的「三級緩存」,為了更容易理解三級緩存,本文先研究這個 bean 對象是什么時候放入緩存的,后面再研究三級緩存。
既然能取,必然有地方把 bean 對象存入了緩存,那緩存中的數據是從哪里來的呢?
下面主要分析單例對象是如何創建、并放入緩存中的。
該邏輯在 AbstractBeanFactory#doGetBean 方法中,主要代碼如下(保留了創建單例 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 對象 // 若創建一個 bean 對象時依賴其他對象,則先創建被依賴對象 // ... // 創建 scope 為 singleton(單例)的對象 if (mbd.isSingleton()) { sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } catch (BeansException ex) { // ... } }); // 處理 FactoryBean 的場景 bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); } // 創建 scope 為 prototype 的對象 else if (mbd.isPrototype()) { // ... } // 創建其他類型對象 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); // 緩存中不存在時再去創建 if (singletonObject == null) { // ... // 創建單例對象前 beforeSingletonCreation(beanName); boolean newSingleton = false; boolean recordSuppressedExceptions = (this.suppressedExceptions == null); if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<>(); } try { // 創建單例對象 singletonObject = singletonFactory.getObject(); newSingleton = true; } // catch ... finally { if (recordSuppressedExceptions) { this.suppressedExceptions = null; } // 創建單例對象后 afterSingletonCreation(beanName); } if (newSingleton) { // 將對象添加到緩存 addSingleton(beanName, singletonObject); } } // 緩存中有的話直接返回 return singletonObject; } } }
getSingleton 方法會先從緩存 singletonObjects(其實就是一個 Map)中獲取 bean 對象,如果緩存有就直接返回,否則再去創建。創建成功后,會把該對象存入緩存。
創建的邏輯在哪呢?
看代碼是通過 ObjectFactory#getObject 方法來創建的,ObjectFactory 是一個函數式接口:
@FunctionalInterface public interface ObjectFactory<T> { T getObject() throws BeansException; }
這個方法的實現是什么呢?退回上一層,即 getBean 方法,看這里:
sharedInstance = getSingleton(beanName, () -> { try { // 創建 bean 對象 return createBean(beanName, mbd, args); } catch (BeansException ex) { // ... } });
這里用到了 Lambda 表達式,將如下表達式作為參數:
() -> { try { // 創建 bean 對象 return createBean(beanName, mbd, args); } catch (BeansException ex) { // ... } }
創建 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 { // 創建 bean 對象 Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } // catch ... } }
值得注意的是,resolveBeforeInstantiation 方法其實是跟 AOP 實現相關的,可能在這里生成代理對象就返回了。由于現在主要分析 IoC 的流程,因此這里暫時略過,有興趣的朋友們可以自行研究。
這里繼續沿著主線邏輯走。
創建 bean 對象是在 doCreateBean 方法中實現的,如下:
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 雖然看起來有點像,但它倆不是一回事,前者是“實例化”,后者是“初始化”。
這個方法看起來有點長,但最主要的事情只有三件:
鴻蒙官方戰略合作共建——HarmonyOS技術社區
創建 bean 對象:createBeanInstance 方法
填充屬性:populateBean 方法
初始化 bean:initializeBean 方法
這幾個方法內部其實都有一大堆堆堆堆堆……的代碼,再對照一下前面給出的整體流程圖 :
就是這樣。
本文在前文整體分析的基礎上又進一步細化,先到這里吧,后面再繼續分析~
小結
如何從 Spring IoC 容器中獲取 bean 對象?前文對此進行了整體流程的分析。
本文在前文的基礎上又進一步細化,主要從整體上探討了 Spring 如何創建單例的 bean 對象,整體上分為三個步驟:
創建 bean 對象。
填充 bean 屬性
初始化 bean 對象
感謝各位的閱讀,以上就是“Spring 如何創建 Bean 對象”的內容了,經過本文的學習后,相信大家對Spring 如何創建 Bean 對象這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。