好问题,阿杰 👍
Spring Bean 的初始化过程是 Spring 框架最核心的机制之一,理解它能帮助你掌握依赖注入(DI)、AOP、生命周期回调等高级特性。
下面我给你讲一个完整、通俗又技术细节兼具的版本👇
🧩 一、整体流程概览
Spring Bean 的生命周期大体上可以分为 7 个阶段:
1️⃣ 实例化(Instantiation)
2️⃣ 属性注入(Populate / Dependency Injection)
3️⃣ BeanNameAware / BeanFactoryAware 等回调
4️⃣ BeanPostProcessor 前置处理(postProcessBeforeInitialization)
5️⃣ 初始化(InitializingBean / @PostConstruct / init-method)
6️⃣ BeanPostProcessor 后置处理(postProcessAfterInitialization)
7️⃣ 使用与销毁(DisposableBean / @PreDestroy / destroy-method)
🧠 二、核心流程详解
1️⃣ 实例化(Instantiation)
Spring 通过 反射 或 构造函数 创建 Bean 实例。
此时对象只是“空壳”,属性还没注入。
🔹 执行位置:
bean = createBeanInstance(beanDefinition);
🔹 示例:
public class UserService {
public UserService() {
System.out.println("1️⃣ 实例化 UserService");
}
}
2️⃣ 属性注入(Populate Bean)
实例化后,Spring 会根据配置或注解(@Autowired
, @Resource
, XML 等)注入依赖对象。
🔹 执行位置:
populateBean(beanName, mbd, instanceWrapper);
🔹 示例:
public class UserController {
@Autowired
private UserService userService; // 此时被注入
}
3️⃣ Aware 接口回调
如果 Bean 实现了某些 “Aware 接口”,Spring 会将相关容器资源注入进来。
常见接口:
接口 | 注入对象 |
---|---|
BeanNameAware | 当前 Bean 的名称 |
BeanFactoryAware | BeanFactory 实例 |
ApplicationContextAware | ApplicationContext 实例 |
🔹 示例:
public class MyBean implements BeanNameAware, ApplicationContextAware {
public void setBeanName(String name) {
System.out.println("3️⃣ BeanNameAware:" + name);
}
public void setApplicationContext(ApplicationContext ctx) {
System.out.println("3️⃣ ApplicationContextAware 回调");
}
}
4️⃣ BeanPostProcessor 前置处理
在初始化前,Spring 会调用 BeanPostProcessor 的:
postProcessBeforeInitialization(Object bean, String beanName)
允许你对 Bean 进行“加工”,比如 AOP 代理增强、属性修改等。
🔹 示例:
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String name) {
System.out.println("4️⃣ BeforeInit:" + name);
return bean;
}
}
5️⃣ 初始化(Initialization)
这是 Bean 真正“就绪”的阶段,可以通过三种方式实现初始化逻辑:
方式 | 描述 |
---|---|
@PostConstruct 注解 | 推荐方式 |
实现 InitializingBean 接口 | 旧式接口方式 |
在 XML 或 JavaConfig 中配置 init-method | 手动指定 |
🔹 示例:
@Component
public class MyService implements InitializingBean {
@PostConstruct
public void init1() { System.out.println("5️⃣ @PostConstruct 调用"); }
@Override
public void afterPropertiesSet() {
System.out.println("5️⃣ InitializingBean.afterPropertiesSet()");
}
public void customInit() {
System.out.println("5️⃣ init-method 调用");
}
}
调用顺序通常是:
@PostConstruct → afterPropertiesSet() → init-method
6️⃣ BeanPostProcessor 后置处理
初始化完成后,再次执行:
postProcessAfterInitialization(Object bean, String beanName)
此时 Bean 已可用,AOP 代理、事务增强通常在此阶段生成。
🔹 示例:
public Object postProcessAfterInitialization(Object bean, String name) {
System.out.println("6️⃣ AfterInit:" + name);
return bean;
}
7️⃣ 使用与销毁
Bean 被使用中……(被依赖、被调用、被注入到控制器等)
当容器关闭时(如 context.close()
),Spring 会执行销毁回调:
方式 | 描述 |
---|---|
@PreDestroy 注解 | 推荐方式 |
实现 DisposableBean 接口 | 旧式接口方式 |
XML 或 JavaConfig 中配置 destroy-method | 手动方式 |
🔹 示例:
@PreDestroy
public void preDestroy() { System.out.println("7️⃣ @PreDestroy 调用"); }
@Override
public void destroy() { System.out.println("7️⃣ DisposableBean.destroy()"); }
public void customDestroy() { System.out.println("7️⃣ destroy-method 调用"); }
调用顺序通常为:
@PreDestroy → destroy() → destroy-method
📊 三、完整调用顺序图
实例化 → 属性注入 → Aware 回调
↓
BeanPostProcessor.beforeInit()
↓
@PostConstruct / afterPropertiesSet() / init-method
↓
BeanPostProcessor.afterInit()
↓
Bean Ready
↓
@PreDestroy / destroy() / destroy-method
🧩 四、实用小结
环节 | 常用注解/接口 | 功能 |
---|---|---|
初始化前 | BeanPostProcessor | 自定义初始化逻辑前处理 |
初始化 | @PostConstruct , InitializingBean | 初始化方法 |
初始化后 | BeanPostProcessor | 增强或AOP代理 |
销毁 | @PreDestroy , DisposableBean | 资源释放 |
发表回复