分析 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)