Skip to content

拷问记录:代理模式和SpringAOP

  • 时间:2026-06-08 09:07
  • 得分:85/100
  • 状态:✅ 过关
  • 知识点来源:[[Spring AOP]]

题目与复盘

1. 什么是 Spring AOP?它主要用来解决开发中的什么痛点?

  • 用户回答摘要:解释了AOP是面向切面编程,用于处理如鉴权、日志、事务等和业务无关的功能,避免代码耦合和冗余。提到了基于代理模式实现解耦。
  • 缺失点:回答非常完美,没有明显缺失。
  • 推荐答案与项目口径:Spring AOP 的本质是“不修改核心业务代码,在方法调用前后动态织入一段通用增强逻辑”。通过代理机制把横切逻辑(日志、事务、权限等)从业务主线剥离,降低重复代码和模块耦合。

2. Spring AOP 的底层原理与区别(JDK vs CGLIB)

  • 用户回答摘要:指出了JDK要求接口,CGLIB通过生成子类实现。Spring优先使用JDK。提到CGLIB需要外部依赖。
  • 缺失点:虽然提到了CGLIB外部依赖,但现在的Spring(3.2+)中CGLIB已经内置,可以直接说基于继承机制。
  • 推荐答案与项目口径
    • JDK动态代理:基于接口,生成接口实现类,调用进入 InvocationHandler#invoke
    • CGLIB动态代理:基于继承生成目标类的子类,调用进入方法拦截器。
    • 默认策略:有接口默认JDK,没接口用CGLIB。可以通过配置强制全部使用CGLIB。

3. 同类自调用导致 AOP 失效及 CGLIB 局限性

  • 用户回答摘要:准确指出内部this调用绕过代理对象导致失效。明确指出了CGLIB因为继承机制无法增强final或private修饰的方法。
  • 缺失点:回答精准。
  • 推荐答案与项目口径:Spring AOP增强生效的前提是请求必须经过代理对象。同类内部方法互相调用时,实际上是目标对象本身发起的调用,跳过了外层的代理封装,因此事务、日志等均会失效。由于CGLIB是生成子类继承,finalprivate 方法无法被重写,自然无法织入通知。

4. 项目实战:解决同类自调用与事务加锁顺序

  • 用户回答摘要:总结了解决自调用的三种方案(自己注入自己、拆分类、AOP获取代理对象),明确项目使用了第三种。但在分布式锁和事务顺序问题上遗忘了。
  • 缺失点:忘记了Redisson分布式锁和Spring事务嵌套顺序的设计原因。
  • 推荐答案与项目口径
    • 自调用解决:使用 AopContext.currentProxy() 在主线程提前拿到代理对象,再通过代理对象去调用事务方法,让事务生效。
    • 锁与事务顺序(核心项目亮点)必须把分布式锁包在事务调用的外层。如果把获取/释放锁写在事务方法内部,那么当业务执行完后,锁先释放了,但此时Spring AOP的事务可能还没来得及向数据库提交(提交动作在拦截器后置处理中)。如果这时其他并发请求拿到了锁进来读数据库,就会读到未提交的旧数据(脏读或超卖现象)。因此,必须确保锁的边界大于事务边界

下次复习动作

  • 重点复习“分布式锁与声明式事务”嵌套使用的边界控制和并发安全性,这是写在简历上展示你对高并发细节把控能力的绝佳口径!