文章目录
- 前言
- 一、BeanPostProcessor:Spring最核心扩展点(灵魂🔥)
- [二、AOP 是怎么"织入"的?(真正流程🔥)](#二、AOP 是怎么“织入”的?(真正流程🔥))
-
- [① Spring 扫描到 @Transactional](#① Spring 扫描到 @Transactional)
- [② 注册一个关键组件](#② 注册一个关键组件)
- [③ Bean 初始化后触发](#③ Bean 初始化后触发)
- [④ 判断这个方法要不要增强](#④ 判断这个方法要不要增强)
- [⑤ 创建代理对象](#⑤ 创建代理对象)
- [⑥ 返回代理对象(替换原Bean)](#⑥ 返回代理对象(替换原Bean))
- 调用链:
- [三、@Transactional 底层调用链(重点🔥)](#三、@Transactional 底层调用链(重点🔥))
- 四、为什么构造器注入无法解决循环依赖?(高频难点🔥)
- [五、Spring 如何"提前暴露代理对象"?(高级🔥)](#五、Spring 如何“提前暴露代理对象”?(高级🔥))
- [六、Spring 整体设计精髓(你要真正理解的)](#六、Spring 整体设计精髓(你要真正理解的))
-
- [① 延迟创建(Lazy + 半成品)](#① 延迟创建(Lazy + 半成品))
- [② 动态增强(代理)](#② 动态增强(代理))
- [③ 生命周期钩子(BPP)](#③ 生命周期钩子(BPP))
- 七、你现在的层级(很重要)
- 八、下一层(架构级进阶)
-
- [🔥 1. Spring 事务传播机制(面试必问)](#🔥 1. Spring 事务传播机制(面试必问))
- [🔥 2. Spring 事务 vs MySQL 事务关系](#🔥 2. Spring 事务 vs MySQL 事务关系)
- [🔥 3. AOP 调用链(责任链模式)](#🔥 3. AOP 调用链(责任链模式))
- [🔥 4. Spring Boot 自动配置原理](#🔥 4. Spring Boot 自动配置原理)
- [🔥 5. 为什么 Spring 启动这么慢?](#🔥 5. 为什么 Spring 启动这么慢?)
- 最后一段总结(建议你内化)
前言
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 自动配置源码拆解"