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 自动配置源码拆解"

相关推荐
GetcharZp2 小时前
GitHub 49K+ Star!C++ 开发者必知的 JSON 神级库:从零到精通全指北
后端
xujinwei_gingko2 小时前
SpringBoot整合WebSocket
spring boot·后端·websocket
智码看视界2 小时前
现代Web开发基础:全栈工程师的起航点
前端·后端·c5全栈
程序员cxuan2 小时前
Claude Fable 5 来了
人工智能·后端·程序员
JS菌2 小时前
手写一个 AI Agent 全栈项目:从沙箱执行到子智能体的完整实现
前端·人工智能·后端
wang09073 小时前
自己动手写一个spring之IOC_2
java·后端·spring
来杯@Java3 小时前
学生选课管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·maven·mybatis
ltl3 小时前
推理退化:为什么大模型会输出乱码、死循环和无意义文本
后端
ltl3 小时前
架构视图与文档:C4 模型从入门到实战
后端