什么是代理Bean?

什么是代理Bean?

大家好,我是程序员花卷,现在是一名大三学生,在持续学习进步,在这里分享一些我的学习感悟和积累

​ 之前面试的时候,面试官问我SpringBean的生命周期 ,我非常流利的答出来了,然后面试官追问: 代理Bean是生命周期是咋样的?普通bean的生命周期和代理bean他们之间加载的区别是什么?我就直接卡壳了,今天我们来一起学习一下代理Bean,让你面试的时候遇到这个问题也能凯凯而谈。

首先我们先搞懂什么是代理 Bean?

普通 Bean:容器实例化的原始目标对象 (target),就是你写的业务类本身。

代理 Bean:Spring 生成的包装对象,包装了原始目标 Bean。调用代理 Bean 方法时,会先执行 AOP 切面逻辑(前置、后置、异常通知),再去调用原始对象的目标方法。

关键点:放到 Spring 容器中的引用,是代理对象 ,代理内部持有target(原始普通 bean)。 例如 @Transactional 事务也是 AOP 代理,拿到的 bean 是代理 bean,不是原始类对象。

在来看看代理 Bean 是如何加载 / 创建的?
时机:Bean 的后置处理,AbstractAutoProxyCreator(核心)

代理不是在实例化阶段创建 ,是在普通 Bean 实例化、属性填充、初始化完成之后,由BeanPostProcessor做替换。 完整流程:

  1. Spring 执行实例化 → 反射 new 出原始目标普通 Bean 对象 (target 对象),完成依赖注入、@PostConstruct、InitializingBean 初始化。
  2. AbstractAutoProxyCreator(实现SmartInstantiationAwareBeanPostProcessor)的 postProcessAfterInitialization 触发。
  3. 判断当前 Bean 是否匹配切面表达式(pointcut),需要 AOP 增强:
    • 如果匹配 → 使用 JDK / CGLIB 生成代理对象(代理 Bean)。代理对象内部持有 target(原始 bean)。
    • 不匹配 → 返回原来普通 Bean,不代理。
  4. Spring 把代理对象放回单例池 ,后续getBean()、@Autowired 注入拿到的就是代理 Bean,而不是原始对象。

⚠️重要:原始目标 Bean 依然存在,只是容器对外暴露的引用被替换成代理。

在来看看普通 Bean 和 代理 Bean 加载、生命周期区别
普通 Bean 完整生命周期
  1. 实例化(反射构造器 new 对象)
  2. 属性填充 populateBean(@Autowired 注入)
  3. BeanPostProcessor before 初始化
  4. 初始化:@PostConstruct → InitializingBean → init‑method
  5. BeanPostProcessor after 初始化
  6. 放入单例池,对外提供使用
代理 Bean 的流程
  1. 实例化:new 原始目标对象(普通对象)
  2. 属性填充
  3. before 初始化后置处理器
  4. 初始化(@PostConstruct、InitializingBean 全部执行在原始 target 对象上)
  5. postProcessAfterInitialization:生成代理对象

✨注意:代理对象没有执行构造器、没有走属性注入、不走初始化方法!初始化全部发生在原始 target 上。

  1. 将代理对象存入单例池;原始 target 对象被代理持有,不再直接对外暴露。
核心对比区别
维度 普通 Bean AOP 代理 Bean
实例是谁 业务类本身 JDK 代理类 / CGLIB 子类对象
构造器调用 容器反射调用本类构造器 代理对象本身不会执行业务类构造器;构造器只调用在原始 target 对象
属性注入 populateBean 给当前对象注入属性 属性注入只做给原始 target;代理对象不做属性填充
初始化方法 (@PostConstruct 等) 在自身对象执行 全部执行原始 target 对象,代理对象不执行初始化回调
创建时机 instantiate 阶段直接创建 原始 bean 完成初始化后,BeanPostProcessor 后置阶段动态生成
单例池存放 存放自己本身对象 存放生成后的代理对象;原始 target 被代理内部引用
方法调用 直接执行业务逻辑 先走切面通知逻辑,再委托调用 target 目标方法
高频面试坑
  1. @PostConstruct写在被 AOP 代理的类上:执行的是原始 target 对象,不是代理对象。
  2. this 调用本类方法不经过 AOP:因为this拿到的是原始 target 对象,不是容器中的代理 Bean,切面失效。
  3. CGLIB 代理是子类,但不会通过子类构造器创建目标业务对象,业务对象是独立 new 出来的 target,代理只是包装。

通过这个希望你对代理bean有了一定的认识,我是程序员花卷,持续学习中,如果你觉得文章有帮助,请帮忙转发给更多的好友,感谢大家的阅读。

相关推荐
柠檬味拥抱2 小时前
RDD2022道路损伤检测数据集 | 3600张YOLO智慧交通数据集
后端
asong2 小时前
没有源代码,AI 也能拆解软件:这个开源项目已有 3.7 万 Star
javascript·后端·github
知守观2 小时前
18年老兵的十条开发军规:每条背后都是一个翻车现场
java·后端·程序员
韩振方2 小时前
为什么 curl -I 显示 200,页面打开还是报错?
后端
小稀土1232 小时前
9 类行业怎么用私有化部署研发管理工具:涉密、制造、金融、科研院所一次盘全
后端
懒洋洋不想起床2 小时前
DEX 与未来交易市场:为什么去中心化金融正在进入新阶段
后端
东风微鸣2 小时前
Rook-Ceph 数据修复实战
后端
imDwAaY2 小时前
WebSocket 和 SSE 有什么区别?从实时通信到 AI 流式输出
后端·websocket