Spring最核心扩展点:BeanPostProcessor

文章目录


前言

4 个核心:

👉 BeanPostProcessor

👉 AOP 是在哪一步"插进去"的

👉 @Transactional 底层调用链

👉 为什么构造器注入解决不了循环依赖


一、BeanPostProcessor:Spring最核心扩展点(灵魂🔥)

它是干嘛的?

一句话:

👉 在 Bean 初始化前后"动手脚"


接口长这样:

java 复制代码
public interface BeanPostProcessor {

    Object postProcessBeforeInitialization(Object bean, String beanName);

    Object postProcessAfterInitialization(Object bean, String beanName);
}

执行时机

text 复制代码
实例化 → 依赖注入 → before → 初始化 → after

最关键点来了:

👉 AOP 就是在这里做的!!!


举个核心逻辑(简化版)

java 复制代码
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {

    if (这个bean需要AOP) {
        return 创建代理对象(bean);
    }

    return bean;
}

结论

👉 你拿到的 Bean:

text 复制代码
可能已经不是原对象,而是"代理对象"

二、AOP 是怎么"织入"的?(真正流程🔥)

完整流程(重要):


① Spring 扫描到 @Transactional

java 复制代码
@Transactional
public void createOrder() {}

② 注册一个关键组件

text 复制代码
InfrastructureAdvisorAutoProxyCreator

👉 本质:一个 BeanPostProcessor


③ Bean 初始化后触发

text 复制代码
postProcessAfterInitialization()

④ 判断这个方法要不要增强

text 复制代码
有没有 @Transactional / @Cacheable / @Aspect

⑤ 创建代理对象

text 复制代码
ProxyFactory → 生成代理

⑥ 返回代理对象(替换原Bean)

👉 容器里放的是代理


调用链:

text 复制代码
你调用方法
 ↓
代理对象
 ↓
事务拦截器(TransactionInterceptor)
 ↓
目标方法

三、@Transactional 底层调用链(重点🔥)

当你调用:

java 复制代码
orderService.createOrder();

实际执行:


1️⃣ 进入代理对象

text 复制代码
CglibAopProxy.invoke()

2️⃣ 进入拦截器链

text 复制代码
TransactionInterceptor.invoke()

3️⃣ 开启事务

text 复制代码
PlatformTransactionManager.getTransaction()

4️⃣ 执行业务代码

text 复制代码
method.invoke()

5️⃣ 提交 or 回滚

text 复制代码
commit() / rollback()

核心类

作用
TransactionInterceptor 事务拦截器
PlatformTransactionManager 事务管理器
DataSourceTransactionManager JDBC实现

一句话总结

👉
@Transactional 本质是一个 AOP 拦截器,在方法执行前后控制事务


四、为什么构造器注入无法解决循环依赖?(高频难点🔥)


构造器注入:

java 复制代码
@Component
class A {
    public A(B b) {}
}

@Component
class B {
    public B(A a) {}
}

问题在哪?

text 复制代码
创建 A → 必须先有 B
创建 B → 必须先有 A

👉 死锁


为什么字段注入可以?

java 复制代码
@Autowired
private B b;

流程:

text 复制代码
1. 先 new A(空对象)
2. 再注入 B

👉 可以"提前暴露半成品"


核心区别

注入方式 是否允许半成品
构造器注入 ❌ 不允许
字段/Setter ✅ 允许

本质原因

👉
构造器必须"完全准备好"才能创建对象
而字段注入可以"先创建再补充"


五、Spring 如何"提前暴露代理对象"?(高级🔥)

结合 AOP + 循环依赖:


问题:

如果 A 被代理:

text 复制代码
B 注入的是原对象 ❌
A 最终变成代理对象 ❌

👉 不一致!


解决方案:

三级缓存第3层:

text 复制代码
singletonFactories

存的是:

text 复制代码
ObjectFactory(可以生成代理对象)

当 B 需要 A:

text 复制代码
直接生成"代理版本的A"

👉 保证一致


六、Spring 整体设计精髓(你要真正理解的)

Spring 做了三件非常难的事:


① 延迟创建(Lazy + 半成品)

text 复制代码
解决循环依赖

② 动态增强(代理)

text 复制代码
实现事务 / AOP

③ 生命周期钩子(BPP)

text 复制代码
允许框架扩展

七、你现在的层级(很重要)

如果你能理解到这里:

👉 已经超过 80% Java 开发

但再往上,你要关注:


八、下一层(架构级进阶)

我可以继续带你深入这些"真正难点":


🔥 1. Spring 事务传播机制(面试必问)

text 复制代码
REQUIRED / REQUIRES_NEW / NESTED

为什么嵌套事务会出问题?


🔥 2. Spring 事务 vs MySQL 事务关系

text 复制代码
Spring ≠ 数据库事务

ThreadLocal 是怎么用的?


🔥 3. AOP 调用链(责任链模式)

多个切面如何排序?


🔥 4. Spring Boot 自动配置原理

text 复制代码
@EnableAutoConfiguration 到底干了啥?

🔥 5. 为什么 Spring 启动这么慢?

如何优化?


最后一段总结(建议你内化)

👉
Spring 的本质不是"帮你写代码",而是一个"对象运行时平台":
通过 Bean 生命周期管理 + 三级缓存解决依赖问题 + 动态代理实现横切能力,从而构建可扩展的企业级系统。


下一步可以带你进入:

👉 "事务传播机制 + 分布式事务(Seata)"

👉 或 "Spring Boot 自动配置源码拆解"

相关推荐
古法安卓3 小时前
Android-日志系统源码解析
android·java·android studio
程序员cxuan3 小时前
Claude 官方的学习教程,太强了。
人工智能·后端·程序员
老孙讲技术3 小时前
把工地遮挡和掉线接进项目部:setMessageCallback 订 alarm 与 deviceStatus
后端·物联网·音视频开发
老孙讲技术3 小时前
关店后有人进门,监控值班群却没响:用 setMessageCallback 订 human,再用 aiHuman 打开人形
后端·物联网·音视频开发
LEE3 小时前
原来 Claude Code 最厉害的工具,一行代码都不写
前端·后端
老孙讲技术3 小时前
把园区几百路摄像头收进值班台账:bindDevice 入账与 listDeviceDetailsByPage 翻页
后端·物联网·音视频开发
用户7813667114453 小时前
emplace_back vs push_back 详解
后端
老孙讲技术3 小时前
把没网没电的户外点位接进出画值班台:unBindDeviceInfo 核 SIMCard 与 bindDeviceLive
后端·物联网·音视频开发
万物智能3 小时前
硬件调试三板斧—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
后端·架构
小夏coding4 小时前
从"一把梭"到"精妙拆解" —— 滑动窗口计时框架的设计演进
java·后端