Spring IoC createBean 方法詳解
阿新 • • 發佈:2020-05-21
# 前言
本篇文章主要分析 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);