但使书种多,会有岁稔时。这篇文章主要讲述老王读Spring IoC-3Spring bean 的创建过程相关的知识,希望能为你提供帮助。
@[TOC](bean 的创建过程)
前言Spring 提供了"
控制反转"
的能力,也就是将 bean 的创建交由 Spring 去统一处理。
前文分析了要实现"
控制反转"
的功能,Spring 需要解决的问题是:
- BeanDefinition 的扫描和注册
- 根据 BeanDefinition 来创建 bean 的实例
上一篇已经分析了 BeanDefinition 的扫描和注册,这里我们主要再分析一下 bean 实例的创建过程。
版本约定Spring 5.3.9 (通过 SpringBoot 2.5.3 间接引入的依赖)
正文【老王读Spring IoC-3Spring bean 的创建过程】一个普通的单例 bean,如果没有特殊的指定 FactoryMethod 或者 constructor 的话,就会使用默认的构造函数来创建 bean 的实例。
那么,我们可以为一个普通的单例 bean 添加一个默认的构造函数,然后在上面打上断点,来观察 bean 实例创建时的调用堆栈。
从调用堆栈中,可以看到,bean 实例的创建是在执行
AbstractApplicationContext#finishBeanFactoryInitialization()
的时候,调用 AbstractBeanFactory#getBean()
触发的。最终会调用
AbstractAutowireCapableBeanFactory#createBeanInstance()
:/**
* 通过一定的实例化策略,为指定的 bean 创建一个新的实例。
* 实例化策略为:FactoryMethod -->
constructor autowiring(构造注入) -->
simple instantiation(调用默认构造函数)
* Create a new instance for the specified bean, using an appropriate instantiation strategy: factory method, constructor autowiring, or simple instantiation.
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class<
?>
beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null &
&
!Modifier.isPublic(beanClass.getModifiers()) &
&
!mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isnt public, and non-public access not allowed: " + beanClass.getName());
}Supplier<
?>
instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}// 1. 通过指定的 FactoryMethod 来创建 bean 的实例
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
} else {
return instantiateBean(beanName, mbd);
}
}// 2. 构造注入
// Candidate constructors for autowiring?
Constructor<
?>
[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}// 3. 使用无参构造函数来创建 bean 的实例。(即默认的构造函数)
// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}
补充:bean 创建的完整过程
createBeanInstance()
方法只是将 bean 的实例创建出来了,它还不是一个完整的 bean,因为 bean 里面依赖的属性还没有填充值。AbstractAutowireCapableBeanFactory.doCreateBean()
的源码可以看到 bean 完整的创建过程:文章图片
小结bean 实例的创建是在执行
AbstractApplicationContext#finishBeanFactoryInitialization()
的时候,调用 AbstractBeanFactory#getBean()
触发的。最终是由
AbstractAutowireCapableBeanFactory#createBeanInstance()
方法来完成 bean 实例的创建的。bean 实例的创建策略为(优先级级从前往后):
- 通过指定的 FactoryMethod 来创建
- 构造注入的方式(通过指定的构造函数)
- 通过默认的构造函数来创建
- AbstractAutowireCapableBeanFactory#createBeanInstance()
创建 bean 的实例 - AbstractAutowireCapableBeanFactory#populateBean()
填充 bean 的依赖 - AbstractAutowireCapableBeanFactory#initializeBean()
初始化 bean。
对 bean 的实例执行一些初始化方法:
awareMethods --> BeanPostProcessor --> initMethod(InitializingBean#afterPropertiesSet、指定的 initMethod)
有关 Spring 源码方面的问题欢迎一起交流,备注:51cto (vx: Kevin-Wang001)
推荐阅读
- ES6学习 第三章 字符串的扩展
- 用云开发搭建的微信答题小程序v1.0
- 11 图 | 硬核讲解 Eureka 增量同步的原理 #yyds干货盘点#
- Git教程 git pull 和 git clone的区别
- 本图文详细教程教你win10电脑蓝屏因素排查及处理办法大
- 自定义CSS和JS无法在WordPress上加载
- 自定义端点API,可通过按单词返回False值获取所有主题
- WordPress中的自定义属性
- WP自定义归档和分页