首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >手撕Spring底层系列之:后置处理器“PostProcessor”

手撕Spring底层系列之:后置处理器“PostProcessor”

作者头像
Xxtaoaooo
发布2025-10-13 15:27:59
发布2025-10-13 15:27:59
2300
代码可运行
举报
文章被收录于专栏:Debug日志Debug日志
运行总次数:0
代码可运行

人们眼中的天才之所以卓越非凡,并非天资超人一等而是付出了持续不断的努力。1万小时的锤炼是任何人从平凡变成超凡的必要条件。———— 马尔科姆·格拉德威

🌟 嗨,我是Xxtaoaooo!

本系列将用源码解剖+拆分核心轮子的方式,带你暴力破解Spring底层逻辑。 警告:阅读后可能导致看Spring源码时产生「庖丁解牛」般的快感! 话不多说,直接开干!

一、后置处理器的概念

后置处理器是Spring留给开发者的‘手术刀’,允许在Bean生命周期的关键节点进行精准干预。

1.1 核心定义

后置处理器(PostProcessor) 是Spring框架中一类特殊的接口,允许开发者在Bean的实例化、依赖注入及初始化阶段插入自定义逻辑。它并非直接参与业务,而是作为容器级扩展点,动态修改Bean定义(BeanDefinition)或Bean实例本身。

Spring后处理器主要有两种:

  1. BeanFactoryPostProcessor:Bean工厂后处理器,在BeanDefinitionMap填充完毕,Bean实例化之前执行。
  2. BeanPostProcessor:Bean后处理器,一般在Bean实例化之后,填充到单例池singletonObiects之前执行。
代码语言:javascript
代码运行次数:0
运行
复制
// BeanDefinitionRegistryPostProcessor 示例:动态注册Bean
@Component
public class DynamicBeanRegistrar implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
        RootBeanDefinition definition = new RootBeanDefinition();
        definition.setBeanClassName("com.example.DynamicService");
        registry.registerBeanDefinition("dynamicService", definition); // 动态注入Bean
    }
}

1.2 两大核心对比

作用阶段

核心能力

典型应用

BeanFactoryPostProcessor

Bean实例化前

修改Bean属性(如作用域、懒加载)

Property占位符解析PropertySourcesPlaceholderConfigurer

BeanPostProcessor

Bean实例化后

修改Bean实例、代理增强

AOP代理、@Autowired 注解处理

本质区别

  • BeanFactoryPostProcessor 操作的是配方(BeanDefinition),在烹饪前调整食材清单。
  • BeanPostProcessor 操作的是菜品(Bean实例),在烹饪过程中调味。

1.3 设计价值

  • 开闭原则实践:不修改Spring源码即可扩展容器功能(如@AutowiredAutowiredAnnotationBeanPostProcessor实现)。
  • 解耦利器:将横切关注点(如AOP代理、事务管理)与业务代码分离。
  • 生态基石:Spring Boot自动装配、Spring Cloud配置中心均依赖后置处理器动态注册Bean。

二、Bean生命周期扩展时机

2.1 执行步骤与实例化体现

Spring在Bean生命周期中至少6次调用后置处理器,形成精细化的扩展链条

  1. 实例化前拦截 postProcessBeforeInstantiation():可返回代理对象替代原生Bean(如AOP场景)
  2. 构造器推断 determineCandidateConstructors():解决@Autowired构造器选择问题
  3. 合并Bean定义 postProcessMergedBeanDefinition():缓存元数据提升后续注入效率
  4. 属性填充干预 postProcessProperties():实现@Autowired的依赖注入逻辑
  5. 初始化前处理 postProcessBeforeInitialization():触发@PostConstruct方法
  6. 初始化后处理 postProcessAfterInitialization():生成AOP代理对象

三、内置后置处理器解析

3.1 五大核心处理器职责

处理器类名

功能

关联注解/功能

AutowiredAnnotationBeanPostProcessor

处理@Autowired 和@Value

依赖注入

CommonAnnotationBeanPostProcessor

解析@PostConstruct

生命周期回调

AnnotationAwareAspectJAutoProxyCreator

创建AOP代理

@EnableAspectJAutoProxy

ApplicationListenerDetector

注册应用事件监听器

ApplicationListener

PersistenceExceptionTranslationPostProcessor

转换JPA异常

@Repository 异常统一处理

3.2 AOP代理创建流程

1. AOP代理流程

代码语言:javascript
代码运行次数:0
运行
复制
// AbstractAutoProxyCreator#postProcessAfterInitialization
public Object postProcessAfterInitialization(Object bean, String beanName) {
    if (bean != null) {
        // 1. 检查是否需代理
        Object cacheKey = getCacheKey(bean.getClass(), beanName);
        if (!this.earlyProxyReferences.contains(cacheKey)) {
            // 2. 包装为代理对象
            return wrapIfNecessary(bean, beanName, cacheKey);
        }
    }
    return bean;
}

// 关键方法:创建代理
protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors) {
    // 选择JDK动态代理或CGLIB
    if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
        TargetSource ts = getTargetSource(beanClass, beanName);
        if (ts != null) {
            // 生成代理对象
            return proxyFactory.getProxy(getProxyClassLoader());
        }
    }
    return null;
}

2. 自定义后置处理器

代码语言:javascript
代码运行次数:0
运行
复制
public class TimeLogBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        //使用动态代理对目标bean进行增强,返回Proxy对象,进而存储到单例池singletonObjects中
        Object proxyInstance = Proxy.newProxyInstance(
            TimeLogBeanPostProcessor.class.getClassLoader(),
            TimeLogBeanPostProcessor.class.getInterfaces(),
            (proxy, method, args) -> {
                //输出开始时间
                System.out.println(method.getName()+"开始时间"+new Date());
                //执行目标方法
                Object result = method.invoke(bean, args);
                //输出结束时间
                System.out.println(method.getName()+"结束时间"+new Date());
                return result;
            }
        );
        return proxyInstance;
    }
}

四、总结

“优秀的框架设计,往往是把复杂留给自己,把简单留给使用者。” Spring后置处理器的设计完美诠释了这一点——通过标准化扩展点,将容器控制权开放给开发者,同时隐藏底层复杂性。

通过学习Spring后置处理器相关内容,我们可以能了解到:

  1. 动态扩展的本质BeanFactoryPostProcessor修改配方,到BeanPostProcessor加工实例,体现了分层扩展思想
  2. 生态兼容性基石 MyBatis整合(MapperScannerConfigurer)、Spring Boot自动装配均依赖后置处理器动态注册Bean;
  3. 设计模式典范 责任链模式(多处理器顺序执行)、代理模式(AOP)均通过后置处理器落地。

致每一位追求技术深度的开发者:当你下次使用@Autowired时,不妨思考背后的AutowiredAnnotationBeanPostProcessor如何通过postProcessProperties()完成注入——这种从“知其然”到“知其所以然”的蜕变,正是工程师与架构师的分水岭!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-07-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、后置处理器的概念
    • 1.1 核心定义
    • 1.2 两大核心对比
    • 1.3 设计价值
  • 二、Bean生命周期扩展时机
    • 2.1 执行步骤与实例化体现
  • 三、内置后置处理器解析
    • 3.1 五大核心处理器职责
    • 3.2 AOP代理创建流程
  • 四、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档