bean 创建基本思路分析
本文解析了 Spring 的通常创建方法,即 doCreateBean()。首先解析源码。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 根据指定 bean 使用对应策略创建新的实例,如工厂方法、构造函数自动注入、简单初始化
// Instantiate the 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);
}
...
mbd.postProcessed = true;
}
}
// 是否需要提前曝光:单例 & 允许循环依赖 & 当前 bean 正在创建中
// 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) {
...
// 提前暴露 ObjectBean
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 对 bean 进行填充,将各个属性注入
// 若存在依赖于其他 bean 的属性,则会递归初始化依赖 bean
populateBean(beanName, mbd, instanceWrapper);
// 调用初始化方法,比如 init-method
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
...
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);
}
}
// 不为空表示当前 bean 创建后依赖的 bean 却没有全部创建完,即存在循环依赖
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(...);
}
}
}
}
// Register bean as disposable.
try {
// 根据 scope 注册 bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
...
return exposedObject;
}
整理这个函数的思路如下:
- 如果是单例则需要首先清除缓存。
- 实例化 bean,将 BeanDefinition 转换为 BeanWrapper。
转换的大致功能包括:- 如果存在工厂方法则使用工厂方法进行初始化;
- 一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造函数并进行初始化;
- 如果既不存在工厂方法也不存在带有参数的构造函数,则使用默认的构造函数进行 bean 的实例化;
- MergedBeanDefinitionPostProcessor 的应用
bean 合并后的处理,Autowired 注解正是通过此方法实现诸如类型的预解析 - 依赖处理
在 Spring 中会有循环依赖的存在,通过三级缓存和 ObjectFactory 提前暴露的方式解决该问题。 - 属性填充。将所有属性填充到 bean 实例中。
- 循环依赖检查。
Spring 的循环依赖解决只对单例有效,对于 prototype 的 bean 只能抛出异常,所以这里会检测已经加载的 bean 是否已经出现了依赖循环,并判断是否需要抛出异常。 - 注册 DisposableBean
如果配置了destory-method,这里需要注册以便于在销毁时候调用。 - 完成创建并返回
接下来我们将分步详细解析 创建 bean 的每一个步骤。
下面是相关文章索引。
创建 bean 实例 —— createBeanInstance.