一、介绍
我理解的bean加载,是程序从IOC容器获取bean的过程,而创建bean实例只是其中的一个步骤。因为bean实例被创建后,会存入到DefaultSingletonBeanRegistry#singletonObjects缓存中(类型为(ConcurrentHashMap)),程序下次再获取该bean时,就不用再次创建bean实例了。
创建bean实例的方法为:AbstractAutowireCapableBeanFactory#doCreateBean(),本章就来讲述一下这个doCreateBean()方法。
二、bean加载流程
- 获取用户传入name对应的beanName
- 尝试从缓存中获取bean实例
- 缓存中不存在,加载bean实例
3.1. 检查循环依赖
3.2 处理parentBeanFactory
3.3 处理依赖的bean(dependsOn)
3.4 三种bean实例的创建
3.4.1 单例bean的创建
3.4.1.1 获取单例bean,getSingleton()方法
3.4.1.2 准备创建bean,createBean()方法
3.4.1.3 创建bean,doCreateBean()方法(本章解析)
3.4.2 原型bean的创建
3.4.3 根据scope策略创建bean - 从bean实例中获取真正的对象
- 转换对象类型
- 返回对象实例
三、doCreateBean()方法流程图
- 第2步,创建BeanWrapper过程中,会创建对应的bean实例
- 第4步,提前曝光bean目的是为了解决循环依赖。具体是,把创建该bean的ObjectFactory对象存入到DefaultSingletonBeanRegistry#singletonFactories缓存中(HashMap类型),这样在出现循环依赖时,可以从这个缓存中直接取出对应的bean实例。从这里获取的bean会应用SmartInstantiationAwareBeanPostProcessor
四、源码分析
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 1. 清理单例缓存
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 2. 创建BeanWrapper(重要方法)
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
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 {
// 3. MergedBeanDefinitionPostProcessors的应用
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// 是否需要提早曝光:单例&&允许玄幻依赖&&当前bean正在创建中(重要方法)
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");
}
// 4. 提前曝光bean(解决循环依赖),即在bean初始化完成前将创建实例的ObjectFactory加入工厂
// getEarlyBeanReference()方法应用SmartInstantiationAwareBeanPostProcessor
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 5. 属性填充(重要方法)
populateBean(beanName, mbd, instanceWrapper);
// 6. 调用初始化方法,如init-method(重要方法)
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);
}
}
// 7. 循环依赖检查
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
// earlySingletonReference只有在检测到有循环依赖的情况才会不为空
if (earlySingletonReference != null) {
// 如果exposedObject没有在初始化方法中被改变
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);
}
}
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.
try {
// 8. 注册DisposableBean(重要方法)
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
// 创建完成
return exposedObject;
}
结合doCreateBean()方法的代码来看,图中的8个步骤还算清晰。图中4个粉色步骤:创建BeanWrapper、属性填充、调用初始化方法、注册DisposableBean在后面的文章中会一一叙述。