Spring Boot 中关于 Bean 加载、实例化、初始化全生命周期的扩展点

一、先明确: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 实例、修改注入属性
  • 执行时机
    1. postProcessBeforeInstantiation:Bean 实例化前(替代默认实例化逻辑)
    2. postProcessAfterInstantiation:Bean 实例化后 → 属性填充前
    3. 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 实例
  • 执行时机
    1. postProcessBeforeInitialization:初始化方法(如 @PostConstruct、init-method)执行前
    2. 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

五、关键注意事项

  1. 避免提前实例化 Bean :在 BeanDefinitionRegistryPostProcessor/BeanFactoryPostProcessor 中,不要调用 beanFactory.getBean(),否则会触发 Bean 提前实例化,导致扩展点失效;
  2. 优先级控制 :多个同类型扩展点可通过 @Order 注解或实现 Ordered 接口控制执行顺序(数字越小优先级越高);
  3. 性能影响:顶级扩展点(如 BeanDefinitionRegistryPostProcessor)执行时机早,复杂逻辑会影响容器启动速度;
  4. 代理对象注意:BeanPostProcessor 后置处理返回的代理对象,才是容器最终使用的 Bean 实例。

总结

  1. 核心逻辑:Spring Bean 扩展点围绕"定义-实例化-初始化-销毁"全生命周期设计,越靠前的扩展点越能影响 Bean 的"定义",越靠后的扩展点越能影响 Bean 的"实例";
  2. 优先级核心BeanDefinitionRegistryPostProcessor 是最高优先级扩展点,可动态注册 Bean;BeanPostProcessor 是最常用扩展点,可增强 Bean 实例;
  3. 实战选型:根据需求选择对应阶段的扩展点------改定义用前序扩展点,改实例用后序扩展点;
  4. 核心价值:这些扩展点是 Spring 灵活性的核心体现,Spring Boot 自动配置、MyBatis/Dubbo 整合 Spring 都基于这些扩展点实现。

掌握这些扩展点,你不仅能读懂 Spring 底层源码,还能自定义灵活的 Bean 管理逻辑,比如封装自己的 Starter、实现自定义注解解析等。

相关推荐
小飞Coding2 小时前
彻底搞懂 Spring 容器导入配置类:@EnableXXX 与 spring.factories 核心原理
spring boot
悟空码字1 天前
Spring Boot 整合 MongoDB 最佳实践:CRUD、分页、事务、索引全覆盖
java·spring boot·后端
皮皮林5513 天前
拒绝写重复代码,试试这套开源的 SpringBoot 组件,效率翻倍~
java·spring boot
用户908324602735 天前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
用户8307196840826 天前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
Java水解6 天前
Spring Boot 视图层与模板引擎
spring boot·后端
Java水解6 天前
一文搞懂 Spring Boot 默认数据库连接池 HikariCP
spring boot·后端
洋洋技术笔记6 天前
Spring Boot Web MVC配置详解
spring boot·后端
初次攀爬者7 天前
Kafka 基础介绍
spring boot·kafka·消息队列