分析 Bean 初始化过程
Spring Bean 的初始化过程是 Spring 容器在启动时注册、创建和配置 Bean 的一系列步骤,涉及 BeanDefinition 解析、依赖注入、生命周期回调 等。
详细拆解 Spring Bean 初始化的完整流程:
1. BeanDefinition 解析
-
Spring 容器在启动时,首先 扫描
@Component
、@Service
、@Repository
等注解的类。 -
通过
BeanDefinitionRegistry
注册 BeanDefinition(只是定义 Bean,未实例化)。 -
如果使用 XML 配置,则从
applicationContext.xml
解析 Bean 结构。
示例:
<bean id="myBean" class="com.example.MyBean"/>
这一步只是定义 Bean,不会真正创建对象!
2. BeanFactory 准备 & 创建 Bean
Spring 解析所有 BeanDefinition 之后,进入 BeanFactory 阶段:
-
创建单例 Bean(如果
@Scope("singleton")
)。 -
检查 Bean 依赖项(
@Autowired
、@Qualifier
)。 -
构造方法执行(调用
new MyBean()
)。
3. 属性填充(依赖注入)
-
Spring 解析
@Autowired
依赖,并将对应 Bean 注入字段:
@Component
public class MyBean {
@Autowired
private AnotherBean anotherBean;
}
-
如果 Bean 有 setter 方法,Spring 会调用
setXxx()
进行填充。
此时 Bean 还没有调用 @PostConstruct
,生命周期未完成!
4. 调用 InitializingBean.afterPropertiesSet()
如果 Bean 实现了 InitializingBean
,Spring 会执行 afterPropertiesSet()
:
@Component
public class MyBean implements InitializingBean {
@Override
public void afterPropertiesSet() {
System.out.println("Bean 初始化完成!");
}
}
可用于 Bean 初始化后的额外操作,如连接池初始化、任务调度等。
5. 调用 @PostConstruct
如果 Bean 有 @PostConstruct
方法,Spring 会执行:
@PostConstruct
public void init() {
System.out.println("Bean 已完全初始化!");
}
相比 afterPropertiesSet()
,@PostConstruct
更推荐在 Spring Boot 项目中使用。
6. Bean 进入 Spring 容器
- 所有依赖注入 & 初始化逻辑完成后,Bean 被缓存到
DefaultSingletonBeanRegistry
。 - 单例 Bean 会一直存在,直到容器销毁。
7. Bean 销毁(@PreDestroy
或 DisposableBean.destroy()
)
如果 Bean 需要释放资源(如关闭数据库连接),Spring 在容器关闭时执行销毁逻辑:
@PreDestroy
public void cleanup() {
System.out.println("Bean 即将销毁!");
}
总结
- BeanDefinition 解析 → BeanFactory 创建 → 依赖注入 →
afterPropertiesSet()
→@PostConstruct
→ Bean 可用 → 销毁 -
@Autowired
在 Bean 创建后执行,但@PostConstruct
在 Bean 可用后执行 - 单例 Bean 存在于
DefaultSingletonBeanRegistry
,而原型 Bean每次getBean()
时都会创建新对象
注意事项:
-
@Component public class CustomBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { System.out.println(beanName + " 初始化前执行"); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) { System.out.println(beanName + " 初始化后执行"); return bean; } }
适用于调试 Bean 初始化前后的行为。
- 如果 Bean 代理(如
@Transactional
)怎么办?- 如果 Bean 被 Spring 代理(例如使用
@Transactional
或@Async
),它的实际初始化过程 可能额外包含 CGLIB 或 JDK 动态代理:@Service @Transactional public class MyTransactionalService { }
Spring 可能会在初始化阶段使用 CGLIB 生成代理对象,导致
postProcessBeforeInitialization()
里获取的 Bean 不是原始类。验证 Bean 是否被代理:System.out.println(AopUtils.isCglibProxy(myBean)); // true 代表是 CGLIB 代理
- 如果 Bean 被 Spring 代理(例如使用
- Spring Bean 初始化流程如下:
- 实例化 Bean(执行
new MyBean()
) postProcessBeforeInstantiation
(创建前处理)- 执行构造方法,创建 Bean 实例
postProcessProperties
(属性注入前处理)- Spring 进行依赖注入(如
@Autowired
字段填充) postProcessBeforeInitialization
(初始化前处理)- 执行
@PostConstruct
或InitializingBean.afterPropertiesSet()
- Bean 进入 Spring 容器,可供使用
- 实例化 Bean(执行
- 点赞
- 收藏
- 关注作者
评论(0)