news 2026/6/24 16:26:11

关于springAOP的总结

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
关于springAOP的总结

12.4号14:01我终于整理完笔记,理清了所有知识点。
关于spring的两大核心:Ioc和AOP
AOP的底层:动态代理技术

为什么要有AOP?

一般一个系统当中都会有一些系统服务,例如:日志、事务管理、安全等。这些系统服务被称为:交叉业务
这些交叉业务几乎是通用的,不管你是做银行账户转账,还是删除用户数据。日志、事务管理、安全,这些都是需要做的。

这会产生什么问题?

  • 代码的复用性差。
  • 交叉业务与核心业务书写在一起,后期维护难。

AOP做了什么?

为了让代码客户端专注于核心业务代码,也方便维护,从纵向的核心业务把重复的横向业务代码抽离出来,形成一个独立的组件,然后以横向交叉的方式应用到业务流程当中的过程被称为AOP。

AOP底层的实现

AOP底层是靠JDK的自带的动态代理技术和CGLIB的动态代理实现的

  • JDK 动态代理主要用于对接口进行代理,其底层通过在运行时内存中动态生成一个实现了目标
    接口的代理类字节码,并借助 InvocationHandler 实现方法拦截。
  • CGLIB 通过在运行时动态生成目标类的子类(代理类)来实现对类的代理,其底层基于字节码 生成技术,通过继承并重写非 final 方法以插入代理逻辑。
  • 补充:即使目标类有接口,你也可以强制 Spring 使用 CGLIB(通过配置proxyTargetClass true)。

[!NOTE] 前面静态代理中不是说继承的耦合度高吗,为啥CGLIB使用继承实现了动态代理?
它在内存中生成,无关业务代码,也就不存在这类问题。

AOP实现的细节

Spring AOP 的实现细节可以简要概括为以下几点:

  1. 基于代理
    Spring AOP 不修改字节码,而是在运行时为目标 Bean 创建代理对象(JDK 动态代理或 CGLIB),通过代理拦截方法调用。

  2. 代理选择

    • 目标类实现了接口 → 默认使用JDK 动态代理
    • 无接口或配置proxyTargetClass=true→ 使用CGLIB 代理
  3. 织入时机
    在 Bean 初始化完成后,由BeanPostProcessor(如AnnotationAwareAspectJAutoProxyCreator)判断是否需要代理,并将代理对象放入 Spring 容器,替换原始 Bean。

  4. 通知执行
    方法调用时,代理对象通过责任链模式依次执行各类通知(@Before@Around@After等),最后调用目标方法(通过反射)。

  5. 统一适配
    所有通知类型(如MethodBeforeAdvice)最终都被适配成MethodInterceptor,统一在拦截链中执行。

  6. 局限性
    只能拦截public 方法,且self-invocation(内部调用)不会触发 AOP,因为调用的是 this 而非代理对象。

总结:Spring AOP = 动态代理 + BeanPostProcessor + 责任链 + 反射,全程在运行时完成,对业务代码无侵入。

Spring AOP 的实现流程

1.启动时扫描切面

  • Spring 容器启动时,通过@EnableAspectJAutoProxy(或 XML 配置)注册一个特殊的BeanPostProcessorAnnotationAwareAspectJAutoProxyCreator
  • 它会识别所有带@Aspect注解的类,并解析其中的@Before@After@Around等通知,转换成Advisor(包含 Pointcut + Advice)

2.Bean 初始化后判断是否需要代理

  • 当每个 Bean 初始化完成后,上述BeanPostProcessorpostProcessAfterInitialization()方法被调用。
  • 它检查该 Bean 的类和方法是否匹配已有的Pointcut 表达式
  • 如果匹配,就进入代理创建流程。

3.选择代理方式并创建代理对象

  • 判断目标类是否有接口:
    • 有接口 → 默认用JDK 动态代理(生成$Proxy0类)
    • 无接口 或 开启proxyTargetClass=true→ 使用CGLIB(生成Xxx$$EnhancerBySpringCGLIB$$...子类)
  • 创建代理对象,内部持有原始目标对象 + 所有匹配的 Advisor 列表。

4.将代理对象放入容器

  • 这个容器就是 Spring 的 IoC 容器本身
  • 容器中保存的是代理对象,而不是原始 Bean。
  • 后续所有对该 Bean 的依赖注入或获取,都返回这个代理。

5.调用方法时触发拦截链

  • 当调用代理对象的方法时:
    • JDK 代理 → 调用InvocationHandler.invoke()
    • CGLIB 代理 → 调用MethodInterceptor.intercept()
  • 两者都会构建一个MethodInvocation对象,内部包含:目标方法、参数、通知链(List)。

6.按顺序执行通知 + 目标方法

  • 调用methodInvocation.proceed(),以责任链模式依次执行:
    1. @Before通知
    2. @Around的前半部分
    3. 目标方法(通过反射调用)
    4. @Around的后半部分
    5. @AfterReturning(成功)或@AfterThrowing(异常)
    6. @After(最终通知,类似 finally)

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/16 11:27:24

网页编辑器导入Word文档图片并自动上传组件

咱安徽程序员实锤了!最近接了个CMS外包活,客户是做企业官网的,非要给后台新闻编辑器加“文档导入Word一键粘贴”功能——好家伙,需求单写着“要保留Word里的花里胡哨样式,图片、公式、甚至MathType的鬼画符都得给我原模…

作者头像 李华
网站建设 2026/6/19 6:14:19

html5大文件上传插件的开源代码与示例分析

咱福州网工仔实锤了!最近为了毕设焦头烂额——要搞个能打的大文件管理系统,还要兼容IE8这种“上古浏览器”(学校机房那台Win7IE9的老古董,点个按钮都像在玩心跳)。找了一圈后端教程,不是“自己悟”就是“付…

作者头像 李华
网站建设 2026/6/17 16:35:11

基于SpringBoot架构的学生档案管理系统

系统介绍: 基于SpringBoot架构的学生档案管理系统是在当今科学技术进步和教育信息化的背景下应运而生的解决方案。传统的学生档案管理方式存在着效率低下、信息不透明等问题,这不仅增加了学校管理的成本,也影响了教务工作的开展和学生档案的准…

作者头像 李华
网站建设 2026/6/21 8:34:58

Git cherry-pick提取关键PyTorch修复提交

Git cherry-pick 提取关键 PyTorch 修复提交 在大型 AI 团队的日常开发中,一个看似微小的框架 bug 就可能让整个训练任务卡在数据加载阶段。比如最近某项目组反馈:使用 PyTorch v2.7 的多进程 DataLoader 在特定条件下会随机死锁——查了一圈才发现社区早…

作者头像 李华
网站建设 2026/6/19 6:34:39

DiskInfo显示SMART信息解读:判断硬盘寿命

DiskInfo显示SMART信息解读:判断硬盘寿命 在数据中心机房的深夜巡检中,一位运维工程师突然收到一条告警通知——某台关键业务服务器的磁盘“重映射扇区数”异常上升。他迅速登录系统运行 DiskInfo,确认该盘 SMART 属性 ID5 已触发预警。尽管…

作者头像 李华
网站建设 2026/6/17 5:07:10

GitHub Pages部署PyTorch项目静态网站

GitHub Pages部署PyTorch项目静态网站 在人工智能项目开发中,一个常被忽视但至关重要的环节是:如何让别人真正“看到”你的成果。模型训练日志、Jupyter Notebook 和代码仓库固然重要,但如果合作者或评审者需要花半小时配置环境才能运行你的…

作者头像 李华