1. 程式人生 > >Spring IoC createBean 方法詳解

Spring IoC createBean 方法詳解

# 前言 本篇文章主要分析 Spring IoC 的 `createBean()` 方法的流程,以及 `bean` 的生命週期。 下面是一個大致的流程圖: ![Spring IoC createBean 方法流程.png](http://ww1.sinaimg.cn/large/006Vpl27gy1gevuad3hnnj30i70xwtaq.jpg) # 正文 ## AbstractAutowireCapableBeanFactory#createBean ```java @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("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. // 將String型別的class字串,轉換為Class物件,例如在XML中配置的class屬性 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 (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的例項化前回調方法返回非null,直接返回例項,跳過後面步驟 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.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } // 返回bean的例項 return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } } ``` 上面方法如果 `resolveBeforeInstantiation()` 返回非 `null`,則會跳過後面步驟,直接返回例項。這也是一個擴充套件點,給 `BeanPostProcessor` 一個機會來返回代理來替代真正的例項。 ## AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation ```java protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { Object bean = null; // 判斷bean在例項化之前是否已經解析過 if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { // Make sure bean class is actually resolved at this point. // 如果bean是合成的 && 有實現 InstantiationAwareBeanPostProcessor 介面 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { // 解析bean的型別 Class targetType = determineTargetType(beanName, mbd); if (targetType != null) { // 執行bean的例項化前回調 bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName); // 如果例項化前生命週期回撥方法返回的不是null if (bean != null) { // 執行bean的例項化後回撥,因為只能在此處呼叫了 bean = applyBeanPostProcessorsAfterInitialization(bean, beanName); } } } // 如果bean不為空,則將beforeInstantiationResolved賦值為true,代表在例項化之前已經解析 mbd.beforeInstantiationResolved = (bean != null); } return bean; } ``` 上面方法主要是判斷 `bean` 之前沒有解析過並且有註冊 `InstantiationAwareBeanPostProcessor` 介面,然後這裡會呼叫 `bean` 例項化前的回撥方法,如果返回非空,會呼叫 `bean` 例項化後的回撥方法;因為返回非空,後續正常的流程都不會走了,所以只能在此處呼叫。 下面是 `InstantiationAwareBeanPostProcessor` 介面,如下: ```java public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor { /** * Bean 例項化前呼叫,返回非 {@code null} IoC 容器不會對 Bean 進行例項化 並且後續的生命週期回撥方法不 * 呼叫,返回 {@code null} 則進行 IoC 容器對 Bean 的例項化 */ @Nullable default Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException { return null; } /** * Bean 例項化之後,屬性填充之前呼叫,返回 {@code true} 則進行預設的屬性填充步驟,返回 {@code false} * 會跳過屬性填充階段,同樣也會跳過初始化階段的生命週期方法的回撥 */ default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { return true; } /** * Bean 例項化後屬性賦值前呼叫,PropertyValues 是已經封裝好的設定的屬性值,返回 {@code null} 繼續 * 使用現有屬性,否則會替換 PropertyValues */ @Nullable default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException { return null; } /** * 跟上面方法一樣,不過是以前版本使用的 */ @Deprecated @Nullable default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException { return pvs; } } ``` 上面介面提供了三個擴充套件點,如下: * `bean` 例項化前 * `bean` 例項化後 * `bean` 屬性賦值前 這也是 `bean` 例項化的生命週期回撥方法。 ## AbstractAutowireCapableBeanFactory#doCreateBean ```java protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException { // Instantiate the bean. BeanWrapper instanceWrapper = null; if (mbd.isSingleton()) { // 如果bean的作用域是singleton,則需要移除未完成的FactoryBean例項的快取 instanceWrapper = this.factoryBeanInstanceCache.remove(beanName); } if (instanceWrapper == null) { // 通過建構函式反射建立bean的例項,但是屬性並未賦值 instanceWrapper = createBeanInstance(beanName, mbd, args); } // 獲取bean的例項 final Object bean = instanceWrapper.getWrappedInstance(); // 獲取bean的型別 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 { // 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. // bean的作用域是單例 && 允許迴圈引用 && 當前bean正在建立中 boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); // 如果允許bean提前曝光 if (earlySingletonExposure) { if (logger.isTraceEnabled()) { logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references"); } // 將beanName和ObjectFactory形成的key-value對放入singletonFactories快取中 addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)); } // Initialize the bean instance. Object exposedObject = bean; try { // 給 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); } } // 如果允許單例bean提前暴露 if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false); // 只有在檢測到迴圈依賴的情況下才不為空 if (earlySingletonReference != null) { // 如果exposedObject沒有在初始化方法中被改變,也就是沒有被增強 if (exposedObject == bean) { exposedObject = earlySingletonReference; } else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) { String[] dependentBeans = getDependentBeans(beanName);