容器扩展点:BeanPostProcessor 与 Aware

引言

很多“魔法”(属性占位符解析、@Autowired 注入、AOP 代理生成)其实都是容器扩展点在工作。想在 Bean 创建过程中插手,Spring 给了两类钩子:针对 Bean 定义 的 BeanFactoryPostProcessor,和针对 Bean 实例 的 BeanPostProcessor;另有 Aware 系列让 Bean 反向感知容器能力。

核心概念

  • BeanFactoryPostProcessor:容器读取完所有 Bean 定义后、实例化任何 Bean 之前执行,可修改/补充 BeanDefinition(改属性占位符、scope 等)。PropertySourcesPlaceholderConfigurer 就是典型实现。
  • BeanDefinitionRegistryPostProcessor:BFPP 的子接口,额外允许注册新的 Bean 定义,执行时机更早。
  • BeanPostProcessor:作用于每个 Bean 实例的初始化前后——postProcessBeforeInitialization(在初始化回调前)与 postProcessAfterInitialization(在初始化回调后)。AOP 自动代理创建器(AbstractAutoProxyCreator)、@Autowired 处理器都是它。
  • 多个处理器时用 Ordered/PriorityOrdered(或 @Order)控制执行顺序。
  • Aware 接口族:让 Bean 在初始化阶段拿到容器设施——BeanNameAwareBeanFactoryAwareApplicationContextAware(回调里拿 ApplicationContext)、EnvironmentAwareResourceLoaderAwareApplicationEventPublisherAwareMessageSourceAware

代码示例

// 1) BeanPostProcessor:观察每个 Bean 的初始化
@Component
public class LoggingBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println("before init: " + beanName);
        return bean; // 必须原样返回(或返回包装后的代理)
    }
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("after init: " + beanName);
        return bean;
    }
}

// 2) BeanFactoryPostProcessor:实例化前统一改默认 scope
@Component
public class ScopeFixer implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) {
        // 把名称为 task 的 Bean 定义改成 prototype
        BeanDefinition bd = factory.getBeanDefinition("task");
        bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
    }
}

// 3) Aware:容器创建后把 ApplicationContext 交给需要它的 Bean
@Component
public class ContextUser implements ApplicationContextAware {
    private ApplicationContext ctx;
    @Override
    public void setApplicationContext(ApplicationContext ctx) {
        this.ctx = ctx; // 慎用:多数场景直接注入更优雅
    }
}

注意点

  • @Configuration 类里声明 BeanFactoryPostProcessor 相关的 @Bean 必须用 static 方法,否则会提前实例化配置类、破坏后处理器时序。
  • postProcessXxx 的返回值会被当作最终 Bean:忘了 return bean 会注入 null;返回代理对象则替换原 Bean(AOP 正是这么干的)。
  • BeanPostProcessor 作用于容器里所有 Bean(包括它自己之外的每个),逻辑务必轻量、幂等。
  • Aware 回调发生在依赖注入之后、初始化回调之前;能用构造器/@Value 表达就不要用 Aware,保持 Bean 对容器的无感知。
  • 执行顺序:BeanDefinitionRegistryPostProcessor → BeanFactoryPostProcessor → 实例化 → BeanPostProcessor 生效。

小结

扩展点分两层:定义级(BeanFactoryPostProcessor 系,动手早、管 BeanDefinition)与实例级(BeanPostProcessor,围着每个 Bean 的初始化前后转),Aware 是 Bean 反向要资源的窗口。理解这三者,就能读懂 Spring 内部处理器,也能安全地写框架级扩展。

笔记加载中…