Spring 的 Bean 的生命周期
Spring 框架在创建 bean 的时候都会调用 AbstractBeanFactory 类中的 doGetBean 方法;bean 的生命周期从调用 beanFactory 的 getBean 开始,到这个 bean 被销毁,可以总结为以下七个阶段:
1. 处理名称,检查缓存
- 这一步会处理别名,将别名解析为实际名称。
- 对 FactoryBean 也会特殊处理,如果以 & 开头表示要获取 FactoryBean 本身,否则表示要获取其产品。
- 这里针对单例对象会检查一级、二级、三级缓存:
singletonFactories
三级缓存,存放单例工厂对象。earlySingletonObjects
二级缓存,存放单例工厂的产品对象。- 如果发生循环依赖,产品是代理;无循环依赖,产品是原始对象。
singletonObjects
一级缓存,存放单例成品对象。
2. 处理父子容器
- 如果当前容器根据名字找不到这个 bean,此时若父容器存在,则执行父容器的 getBean 流程。
- 父子容器的 bean 名称可以重复。
3. 处理 dependsOn
- 如果当前 bean 有通过 dependsOn 指定了非显式依赖的 bean,这一步会提前创建这些 dependsOn 的 bean。
- 所谓非显式依赖,就是指两个 bean 之间不存在直接依赖关系,但需要控制它们的创建先后顺序。
4. 选择 scope 策略
- 对于
singleton scope
,首先到单例池去获取 bean,如果有则直接返回,没有再进入创建流程。 - 对于
prototype scope
,每次都会进入创建流程。 - 对于自定义
scope
,例如request
,首先到request
域获取 bean,如果有则直接返回,没有再进入创建流程。
5. 创建 bean(关键阶段)
5.1 创建 bean 实例
要点 | 总结 |
---|---|
AutowiredAnnotationBeanPostProcessor |
1. 优先选择带 @Autowired 注解的构造;2. 若有唯一的带参构造,也会入选。 |
采用默认构造 | 如果上面的后处理器和 BeanDefiniation 都没找到构造,采用默认构造,即使是私有的。 |
5.2 依赖注入
要点 | 总结 |
---|---|
AutowiredAnnotationBeanPostProcessor |
识别 @Autowired 及 @Value 标注的成员,封装为 InjectionMetadata 进行依赖注入。 |
CommonAnnotationBeanPostProcessor |
识别 @Resource 标注的成员,封装为 InjectionMetadata 进行依赖注入 |
AUTOWIRE_BY_NAME |
根据成员名字找 bean 对象,修改 mbd 的 propertyValues ,不会考虑简单类型的成员。 |
AUTOWIRE_BY_TYPE |
根据成员类型执行 resolveDependency 找到依赖注入的值,修改 mbd 的 propertyValues |
applyPropertyValues |
根据 mbd 的 propertyValues 进行依赖注入(即 xml 中 <property name ref | value />) |
5.3 初始化
要点 | 总结 |
---|---|
内置 Aware 接口的装配 | 包括BeanNameAware , BeanFactoryAware 等。 |
扩展 Aware 接口的装配 | 由ApplicationContextAwareProcessor 解析,执行时机在 postProcessBeforeInitialization |
PostConstruct |
由 CommonAnnotationBeanPostProcessor 解析,执行时机在 postProcessBeforeInitialization |
InitializingBean |
通过接口回调执行初始化。 |
initMethod |
根据 BeanDefinition 得到的初始化方法执行初始化,即 <bean init-method> 或 @Bean(initMethod) |
5.4 注册可销毁的 bean
在这一步判断并登记可销毁 bean。
-
判断依据
- 如果实现了
DisposableBean
或AutoCloseable
接口,则为可销毁 bean。 - 如果自定义了
destroyMethod
,则为可销毁 bean。 - 如果采用 @Bean 没有指定
destoryMethod
,则采用自动推断方式获取销毁方法名(close,shutdown)。 - 如果由
@PreDestroy
标注的方法。
- 如果实现了
-
存储位置
singleton scope
的可销毁 bean 会存储于beanFactory
的成员当中。- 自定义
scope
的可销毁 bean 会存储于对于的域对象当中。 prototype scope
不会存储,需要自己找到此对象销毁。
-
存储时都会封装为
DisposableBeanAdapter
类型对销毁方法的调用进行适配。
6. 类型转换处理
- 如果
getBean
的requiredType
参数与实际得到的对象类型不同,会尝试进行类型转换。
7. 销毁 bean
- 销毁时机
singleton bean
的销毁在ApplicationContext.close
时,此时会找到所有DisposableBean
的名字,逐一销毁。- 自定义
scope bean
的销毁在作用域对象生命周期结束时。 prototype bean
的销毁可以通过自己手动调用,AutowireCapableBeanFactory.destroyBean
方法执行销毁。
- 同一 bean 中不同形式销毁方法的调用次序
- 优先后处理器销毁,即
@PreDestroy
。 - 其次
DisposableBean
接口销毁。 - 最后
destroyMethod
销毁(包括自定义名称,推断名称,AutoCloseable
接口多选一)。
- 优先后处理器销毁,即
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
· .NET 10 首个预览版发布,跨平台开发与性能全面提升
· 《HelloGitHub》第 107 期
· 全程使用 AI 从 0 到 1 写了个小工具
· 从文本到图像:SSE 如何助力 AI 内容实时呈现?(Typescript篇)