一、先明确:Bean 完整生命周期
先梳理 Spring Bean 从"定义"到"销毁"的完整流程,所有扩展点都嵌入在这个流程中:
csharp
1. 扫描/解析生成 BeanDefinition(Bean 定义)→ 2. 注册 BeanDefinition 到容器 → 3. 实例化 Bean(创建对象)→ 4. 属性填充(依赖注入)→ 5. 初始化前处理 → 6. 初始化(执行 init 方法)→ 7. 初始化后处理 → 8. Bean 就绪使用 → 9. 容器关闭 → 10. 销毁 Bean
二、按生命周期阶段拆解扩展点(优先级+时机+示例)
阶段 1:BeanDefinition 处理阶段(实例化前,最高优先级)
核心目标:修改/新增/删除 BeanDefinition,不涉及 Bean 实例
该阶段扩展点优先级:BeanDefinitionRegistryPostProcessor > BeanFactoryPostProcessor
1. BeanDefinitionRegistryPostProcessor(顶级扩展点)
- 核心作用:动态注册/修改/删除 BeanDefinition(Spring 最早的扩展点)
- 执行时机:扫描生成 BeanDefinition 后 → Bean 实例化前
- 优先级:最高(优先于所有 BeanFactoryPostProcessor)
- 典型场景:Spring Boot 自动配置、MyBatis Mapper 扫描、动态注册 Bean
实战示例:动态注册 UserService Bean
java
@Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 1. 构建 BeanDefinition(描述 UserService 的定义)
RootBeanDefinition userServiceDefinition = new RootBeanDefinition(UserService.class);
// 可选:设置 Bean 属性(如作用域、初始化方法)
userServiceDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);
userServiceDefinition.setInitMethodName("init");
// 2. 注册 BeanDefinition 到容器(Bean 名称:userService)
registry.registerBeanDefinition("userService", userServiceDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 可选:对 BeanFactory 做额外配置(优先级低于上面的方法)
beanFactory.registerSingleton("testBean", new TestBean());
}
}
// 无任何 Spring 注解的业务类
public class UserService {
public void init() {
System.out.println("UserService 初始化方法执行");
}
public void sayHello() {
System.out.println("动态注册的 UserService 就绪");
}
}
// 测试
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(TestApplication.class);
UserService userService = context.getBean(UserService.class);
userService.sayHello(); // 输出:动态注册的 UserService 就绪
}
}
2. BeanFactoryPostProcessor(BeanFactory 配置修改)
- 核心作用:修改已注册的 BeanDefinition 属性(如修改作用域、属性值),不能新增 BeanDefinition
- 执行时机:BeanDefinitionRegistryPostProcessor 执行后 → Bean 实例化前
- 优先级:低于 BeanDefinitionRegistryPostProcessor
- 典型场景:修改 Bean 配置、占位符替换(如 ${spring.datasource.url})
实战示例:修改已有 BeanDefinition 的属性
java
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 1. 获取已注册的 BeanDefinition(假设容器中有 "userService" Bean)
BeanDefinition userServiceDef = beanFactory.getBeanDefinition("userService");
// 2. 修改属性:将单例改为原型
userServiceDef.setScope(BeanDefinition.SCOPE_PROTOTYPE);
// 3. 设置自定义属性
MutablePropertyValues propertyValues = userServiceDef.getPropertyValues();
propertyValues.add("name", "自定义名称");
}
}
阶段 2:Bean 实例化+属性填充阶段(初始化前)
核心目标:干预 Bean 实例的创建和依赖注入
该阶段扩展点:InstantiationAwareBeanPostProcessor(BeanPostProcessor 子接口)
InstantiationAwareBeanPostProcessor(实例化+属性填充拦截)
- 核心作用:拦截 Bean 实例化、属性填充过程,可替换 Bean 实例、修改注入属性
- 执行时机 :
postProcessBeforeInstantiation:Bean 实例化前(替代默认实例化逻辑)postProcessAfterInstantiation:Bean 实例化后 → 属性填充前postProcessProperties:属性填充时(修改注入的属性值)
- 优先级:高于普通 BeanPostProcessor
- 典型场景:自定义依赖注入、字段注解解析(如 @Value、@Autowired)
实战示例:拦截 UserService 实例化和属性填充
java
@Component
public class CustomInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
// 1. 实例化前拦截(可直接返回自定义实例,跳过默认实例化)
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("UserService 实例化前拦截");
// 可选:返回自定义实例(替代 Spring 自动实例化)
// return new UserService();
}
return null; // 返回 null 则走默认实例化逻辑
}
// 2. 实例化后拦截(属性填充前)
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("UserService 实例化后,属性填充前");
}
return true; // 返回 true 才会执行属性填充
}
// 3. 属性填充拦截(修改注入的属性值)
@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("UserService 属性填充拦截");
// 修改属性值(假设 UserService 有 name 字段)
MutablePropertyValues mutablePvs = (MutablePropertyValues) pvs;
mutablePvs.add("name", "拦截后修改的名称");
}
return pvs;
}
}
阶段 3:Bean 初始化阶段(实例化+属性填充后)
核心目标:修改 Bean 实例、执行初始化逻辑
该阶段扩展点优先级:BeanPostProcessor.postProcessBeforeInitialization > 自定义初始化方法 > BeanPostProcessor.postProcessAfterInitialization
1. BeanPostProcessor(初始化前后拦截)
- 核心作用:拦截所有 Bean 的初始化过程,修改 Bean 实例
- 执行时机 :
postProcessBeforeInitialization:初始化方法(如 @PostConstruct、init-method)执行前postProcessAfterInitialization:初始化方法执行后
- 优先级:可通过 @Order 注解控制多个 BeanPostProcessor 的执行顺序
- 典型场景:AOP 代理创建、Bean 增强(如事务代理、缓存代理)
实战示例:拦截 UserService 初始化过程
java
@Component
@Order(1) // 控制优先级(数字越小优先级越高)
public class CustomBeanPostProcessor implements BeanPostProcessor {
// 1. 初始化前处理
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("UserService 初始化前处理");
}
return bean; // 返回修改后的 Bean 实例
}
// 2. 初始化后处理(AOP 代理通常在这里创建)
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("UserService 初始化后处理");
// 可选:返回代理对象(如 JDK 动态代理)
// return Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), (proxy, method, args) -> {
// System.out.println("方法执行前增强");
// return method.invoke(bean, args);
// });
}
return bean;
}
}
2. 自定义初始化方法(3 种方式)
- 核心作用:执行 Bean 专属的初始化逻辑
- 执行时机:BeanPostProcessor 前置处理后 → 后置处理前
- 优先级 :同一 Bean 内优先级:
@PostConstruct>InitializingBean.afterPropertiesSet()>init-method
实战示例:3 种初始化方法对比
java
@Component
public class UserService implements InitializingBean {
private String name;
// 方式 1:@PostConstruct 注解(最常用)
@PostConstruct
public void postConstructInit() {
System.out.println("UserService @PostConstruct 初始化");
}
// 方式 2:实现 InitializingBean 接口
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("UserService InitializingBean 初始化");
}
// 方式 3:XML/注解指定 init-method(传统方式)
public void initMethod() {
System.out.println("UserService init-method 初始化");
}
// getter/setter 省略
}
// 配置类指定 init-method(如果不用注解的话)
@Configuration
public class AppConfig {
@Bean(initMethod = "initMethod")
public UserService userService() {
return new UserService();
}
}
阶段 4:Bean 销毁阶段(容器关闭时)
核心目标:执行 Bean 销毁前的清理逻辑
扩展点优先级:@PreDestroy > DisposableBean.destroy() > destroy-method
自定义销毁方法(3 种方式)
- 核心作用:释放资源(如关闭连接池、销毁线程)
- 执行时机 :Spring 容器关闭时(调用
context.close()) - 典型场景:资源清理、连接关闭
实战示例:3 种销毁方法对比
java
@Component
public class UserService implements DisposableBean {
// 方式 1:@PreDestroy 注解
@PreDestroy
public void preDestroy() {
System.out.println("UserService @PreDestroy 销毁");
}
// 方式 2:实现 DisposableBean 接口
@Override
public void destroy() throws Exception {
System.out.println("UserService DisposableBean 销毁");
}
// 方式 3:XML/注解指定 destroy-method
public void destroyMethod() {
System.out.println("UserService destroy-method 销毁");
}
}
// 配置类指定 destroy-method
@Configuration
public class AppConfig {
@Bean(destroyMethod = "destroyMethod")
public UserService userService() {
return new UserService();
}
}
// 测试销毁
public class TestDestroy {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(TestApplication.class);
// 关闭容器触发销毁
context.close();
}
}
三、所有扩展点优先级总览(从高到低)
| 扩展点/方法 | 执行阶段 | 核心能力 |
|---|---|---|
| BeanDefinitionRegistryPostProcessor | BeanDefinition 注册后 | 新增/修改/删除 BeanDefinition |
| BeanFactoryPostProcessor | BeanDefinition 处理后 | 修改 BeanDefinition 属性 |
| InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation | Bean 实例化前 | 替换 Bean 实例 |
| InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation | Bean 实例化后 | 控制是否执行属性填充 |
| InstantiationAwareBeanPostProcessor.postProcessProperties | 属性填充时 | 修改注入的属性值 |
| BeanPostProcessor.postProcessBeforeInitialization | 初始化前 | Bean 实例增强(如赋值) |
| @PostConstruct | 初始化中(最高) | 注解式初始化逻辑 |
| InitializingBean.afterPropertiesSet() | 初始化中(中间) | 接口式初始化逻辑 |
| init-method | 初始化中(最低) | 配置式初始化逻辑 |
| BeanPostProcessor.postProcessAfterInitialization | 初始化后 | Bean 代理创建(如 AOP) |
| @PreDestroy | 销毁前(最高) | 注解式销毁逻辑 |
| DisposableBean.destroy() | 销毁前(中间) | 接口式销毁逻辑 |
| destroy-method | 销毁前(最低) | 配置式销毁逻辑 |
四、典型应用场景总结
| 业务需求 | 推荐扩展点 |
|---|---|
| 动态注册 Bean | BeanDefinitionRegistryPostProcessor |
| 修改 Bean 配置(如作用域) | BeanFactoryPostProcessor |
| 自定义依赖注入/拦截实例化 | InstantiationAwareBeanPostProcessor |
| Bean 增强(如 AOP、缓存) | BeanPostProcessor(后置初始化) |
| Bean 专属初始化逻辑 | @PostConstruct / InitializingBean |
| 资源清理/连接关闭 | @PreDestroy / DisposableBean |
五、关键注意事项
- 避免提前实例化 Bean :在
BeanDefinitionRegistryPostProcessor/BeanFactoryPostProcessor中,不要调用beanFactory.getBean(),否则会触发 Bean 提前实例化,导致扩展点失效; - 优先级控制 :多个同类型扩展点可通过
@Order注解或实现Ordered接口控制执行顺序(数字越小优先级越高); - 性能影响:顶级扩展点(如 BeanDefinitionRegistryPostProcessor)执行时机早,复杂逻辑会影响容器启动速度;
- 代理对象注意:BeanPostProcessor 后置处理返回的代理对象,才是容器最终使用的 Bean 实例。
总结
- 核心逻辑:Spring Bean 扩展点围绕"定义-实例化-初始化-销毁"全生命周期设计,越靠前的扩展点越能影响 Bean 的"定义",越靠后的扩展点越能影响 Bean 的"实例";
- 优先级核心 :
BeanDefinitionRegistryPostProcessor是最高优先级扩展点,可动态注册 Bean;BeanPostProcessor是最常用扩展点,可增强 Bean 实例; - 实战选型:根据需求选择对应阶段的扩展点------改定义用前序扩展点,改实例用后序扩展点;
- 核心价值:这些扩展点是 Spring 灵活性的核心体现,Spring Boot 自动配置、MyBatis/Dubbo 整合 Spring 都基于这些扩展点实现。
掌握这些扩展点,你不仅能读懂 Spring 底层源码,还能自定义灵活的 Bean 管理逻辑,比如封装自己的 Starter、实现自定义注解解析等。