您好,登錄后才能下訂單哦!
這篇文章主要講解了“Spring Ioc中Bean的加載實現方法”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Spring Ioc中Bean的加載實現方法”吧!
代碼:
//AbstractAutowireCapableBeanFactory.java protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isDebugEnabled()) { logger.debug("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. //判斷需要創建的Bean是否可以實例化,即是否可以通過當前的類加載器加載 Class<?> resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. //校驗和準備Bean中的方法覆蓋 try { mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. //如果Bean配置了初始化前和初始化后的處理器,則試圖返回一個需要創建Bean的代理對象 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { //創建Bean的入口 Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isDebugEnabled()) { logger.debug("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException ex) { // A previously detected exception with proper bean creation context already... throw ex; } catch (ImplicitlyAppearedSingletonException ex) { // An IllegalStateException to be communicated up to DefaultSingletonBeanRegistry... throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
這段代碼分為以下幾個步驟:
判斷需要創建的Bean是否可以實例化,即是否可以通過當前的類加載器加載
校驗和準備Bean中的方法注入
如果Bean配置了初始化前和初始化后的處理器,則試圖返回一個需要創建Bean的代理對象
創建Bean
主要是獲取bean的class,并設置到BeanDefinition中
主要是處理方法注入
代碼:
public void prepareMethodOverrides() throws BeanDefinitionValidationException { // Check that lookup methods exists. //檢測是否存在方法注入,并循環預處理方法注入 if (hasMethodOverrides()) { Set<MethodOverride> overrides = getMethodOverrides().getOverrides(); synchronized (overrides) { //遍歷處理 for (MethodOverride mo : overrides) { prepareMethodOverride(mo); } } } }
prepareMethodOverride(mo):
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException { // 統計注入的方法個數 int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName()); if (count == 0) { throw new BeanDefinitionValidationException( "Invalid method override: no method with name '" + mo.getMethodName() + "' on class [" + getBeanClassName() + "]"); } // 如果為1,則將注入方法標記為未重載 // 注意:當有多個重載方法時,為了確定調用哪個具體的方法,Spring對重載方法的參數解析是很復雜的 // 所以,如果注入方法沒有被重載這里就將其標記,省去了對方法參數的解析過程,直接調用即可 else if (count == 1) { // Mark override as not overloaded, to avoid the overhead of arg type checking. mo.setOverloaded(false); } }
代碼讀到這里,大家可能有疑問,從代碼上看明明是處理的方法重載,但是為什么處理的是方法注入呢?而且如果我們在bean里設置幾個方法重載的話,hasMethodOverrides()
方法返回的是false。如果我們打開 AbstractBeanDefinition 類的 hasMethodOverrides() 方法,就能打消我們之前的疑問。
public boolean hasMethodOverrides() { return (this.methodOverrides != null && !this.methodOverrides.isEmpty()); }
其中methodOverrides
是做什么的呢?通過類名AbstractBeanDefinition我們可以發現,該類是BeanDefinition的一個子類,那么它保存的應該是我們解析到的beanDefinition,spring在解析配置文件的時候,如果發現配置了replace-method
或者lookup-method
那么,就會對應的標簽解析,并存入到 AbstractBeanDefinition 的 methodOverrides 屬性中,那么當bean實例化的時候,如果檢測到了methodOverrides屬性不為空,則動態的為當前bean生成代理并使用相應的攔截器對bean做處理,這里大家只要把概念搞清楚即可。
主要是對bean前置后置處理器的處理,給 BeanPostProcessors 后置處理器一個返回代理對象的機會
詳細代碼:
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { Class<?> targetType = determineTargetType(beanName, mbd); if (targetType != null) { bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); if (bean != null) { bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } mbd.beforeInstantiationResolved = (bean != null); } return bean; }
如果代理對象不為空,則直接返回代理對象,這一步驟有非常重要的作用,Spring 后續實現 AOP 就是基于這個地方判斷的。
這個方法核心就在于 applyBeanPostProcessorsBeforeInstantiation()
和 applyBeanPostProcessorsAfterInitialization()
兩個方法,before 為實例化前的后處理器應用,after 為實例化后的后處理器應用。
doCreateBean()
創建Bean
//真正創建Bean的方法 protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. //BeanWrapper是對Bean的包裝,其接口中所定義的功能很簡單包括設置獲取被包裝的對象,獲取被包裝bean的屬性描述器 BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { //單例模式,刪除factoryBean緩存 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { //使用合適的實例化策略來創建Bean:工廠方法、構造函數自動注入、簡單初始化 instanceWrapper = createBeanInstance(beanName, mbd, args); } //從包裝類中獲取實例化的Bean final 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 { //調用PostProcessor后置處理器,修改 BeanDefinition applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); } catch (Throwable ex) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", ex); } mbd.postProcessed = true; } } // Eagerly cache singletons to be able to resolve circular references // even when triggered by lifecycle interfaces like BeanFactoryAware. // 解決單例模式的循環依賴 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { if (logger.isDebugEnabled()) { logger.debug("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } //這里是一個匿名內部類,為了防止循環引用,盡早持有對象的引用 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. //Bean對象的初始化,依賴注入在此觸發 //這個exposedObject在初始化完成之后返回作為依賴注入完成后的Bean Object exposedObject = bean; try { //將Bean實例對象封裝,并且Bean定義中配置的屬性值賦值給實例對象 populateBean(beanName, mbd, instanceWrapper); //初始化Bean對象 exposedObject = initializeBean(beanName, exposedObject, mbd); } 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); } } if (earlySingletonExposure) { //獲取指定名稱的已注冊的單例模式Bean對象 Object earlySingletonReference = getSingleton(beanName, false); if (earlySingletonReference != null) { //根據名稱獲取的已注冊的Bean和正在實例化的Bean是同一個 if (exposedObject == bean) { //當前實例化的Bean初始化完成 exposedObject = earlySingletonReference; } //當前Bean依賴其他Bean,并且當發生循環引用時不允許新創建實例對象 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName); Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length); //獲取當前Bean所依賴的其他Bean for (String dependentBean : dependentBeans) { //對依賴Bean進行類型檢查 if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) { actualDependentBeans.add(dependentBean); } } if (!actualDependentBeans.isEmpty()) { throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been " + "wrapped. This means that said other beans do not use the final version of the " + "bean. This is often the result of over-eager type matching - consider using " + "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example."); } } } } // Register bean as disposable. //注冊完成依賴注入的Bean try { registerDisposableBeanIfNecessary(beanName, bean, mbd); } catch (BeanDefinitionValidationException ex) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex); } return exposedObject; }
代碼很長,不過別慌,我們來按步驟分析一波
如果是單例模式,從factoryBeanInstanceCache 緩存中獲取BeanWrapper 實例對象并刪除緩存
調用 createBeanInstance()
實例化 bean
(主要是將 BeanDefinition 轉換為 BeanWrapper)
后置處理
單例模式的循環依賴處理
初始化 bean 實例對象
(屬性填充)
依賴檢查
注冊 DisposableBean
doCreateBean()
完成 bean 的創建和初始化工作,內容太多,比較復雜,這里只列出大致流程,接下來我們將分幾篇文章來分別闡述相關內容。
感謝各位的閱讀,以上就是“Spring Ioc中Bean的加載實現方法”的內容了,經過本文的學習后,相信大家對Spring Ioc中Bean的加載實現方法這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。