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

相关推荐
A_aspectJ2 小时前
【Java基础开发】基于 Java Swing +MySQL + JDBC 版实现图书管理系统
java·开发语言·mysql
Mr.45672 小时前
SpringBoot多模块依赖冲突排查与架构优化实战(避坑指南)
java·spring boot·架构
学术阿凡提2 小时前
Spring Boot 优雅实现异步调用:从入门到自定义线程池与异常处理
java·数据库·算法
我是无敌小恐龙2 小时前
Java SE 零基础入门Day06 方法重载+Debug调试+String字符串全套API详解(超全干货)
java·开发语言·人工智能·python·transformer·无人机·量子计算
xiaoye37082 小时前
java接口文档工具 swagger2和swagger3对比
java·服务器·前端
三维频道2 小时前
工业级三维扫描实测:汽车灯具复杂结构件的全尺寸 3D 测量方案分析
java·人工智能·python·数码相机·3d·汽车·汽车轻量化制造
tongyiixiaohuang2 小时前
基于轻易云的数据集成,实现企业系统间灵活对接
java·前端·数据库
码农飞哥2 小时前
从Java后端到AI应用开发,我这两年做了什么
java·开发语言·人工智能
阿丰资源2 小时前
基于SpringBoot智能化体育馆管理系统(附源码+文档+数据库,一键运行)
数据库·spring boot·后端