【Spring】超详细讲解AOP(面向切面编程)
文章目录
- 1. 前言
- 2. 什么是AOP
- 3. AOP快速入门
- 4. AOP的核心概念
- 5. 切点表达式
- 6. 切点函数
- 7. 通知
- 8. 总结
1. 前言
本文围绕AOP进行讲解,AOP可以做什么,涉及到了哪些注解,以及各个注解运行的时机,以及@Around相较于其它注解有什么不同,并且如果要执行目标方法需要怎么做
2. 什么是AOP
Spring的AOP(面向切面编程)是Spring框架的一个重要特性,它允许开发人员在应用程序中通过定义切面来实现横切关注点的功能,如日志记录、性能监控、事务管理等。AOP通过将这些关注点从业务逻辑中抽离出来,使得代码更加模块化、可维护和可重用。
SpringAOP就是批量对Spring容器中bean的方法做增强,并且这种增强不会与原来方法中的代码耦合
3. AOP快速入门
目标:要求service包下所有的类中的方法调用前输出: “方法被调用了”
在学AOP前,大家可能会在每个方法内添加一个输出语句. 但如果类很多,类中的方法也很多,添加起来也很麻烦,而且如果后续要进行修改,也很麻烦
- 首先要引入相关依赖:
<dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.29</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7</version></dependency>
</dependencies>
- 把相关bean放到Spring容器中
可以使用注解@ComponentScan(basePackages = "com.example"),也可以在xml配置文件中,使用<context:component-scanbase-package="com.example"></context:component-scan>

因为我的代码结构是这样的,所以是com.example.
- 实现AOP
实现AOP可以使用注解,也可以使用xml配置文件. 因为是入门,所以先认识一下注解实现AOP的方式
①开启AOP注解支持
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
②创建切换类
其实就是普通的类,加上@Component和x @Aspect这两个注解而已
使用使用@Pointcut注解来指定要被强的方法
使用@Before注解来给我们的增湿代码所在的方法进行标识,并且指定了增强代码是在被增强方法执行之前执行
的。
示例:
@Component
@Aspect
public class MyAspect {@Pointcut("execution(* com.example.service.*.*(..))")public void point(){}@Before("point()")public void methodBefore(){System.out.println("方法被调用了");}
}
@Pointcut("execution(* com.example.service.*.*(..))")
这段代码:是指 对com.example的service包下类的所有方法进行增强
@Before("point()")public void methodBefore(){System.out.println("方法被调用了");}
@Before("point()")是指选中point()这个切点表达式的方法进行增强,增强的内容就是方法中的代码
UserService:
@Service
public class UserService {public void update(){System.out.println("执行了UserService的update方法");}
}
准备工作完成,进行测试.

可以看到在执行UserService的update()方法前,输出了"方法被调用了"
4. AOP的核心概念
- Joinpoint (连接点): 所谓连接点是指那些可以被增强到的点。在spring中,这些点指的是方法,因为spring
只支持方法类型的连接点 - ⭐Pointcut (切入点) : 所谓切入点是指被增强的连接点(方法)
- Advice (通知/ 增强) : 所谓通知是指具体增强的代码
- Target (目标对象): 被增强的对象就是目标对象
- Aspect (切面) : 是切入点和通知(引介) 的结合
- Proxy (代理) : 一个类被 AOP 增强后,就产生一个结果代理类
5. 切点表达式
切点表达式用来表示要对哪些方法进行增强
写法: execution([修饰符] 返回值类型 包名.类名.方法名(参数))
- 访问修饰符可以省略,大部分情况下可以省略
- 返回值类型、包名、类名、方法名可以使用星号
*代表任意包 - 名与类名之间一个点
.代表当前包下的类,两个点..表示当前包及其子包下的类 - 参数列表可以使用两个点
..表示任意个数,任意类型的参数列表
如快速入门中的切点表达式:
execution(* com.example.service.*.*(..))
该切点表达式就是 对com.example的service包下类的所有方法进行增强,
6. 切点函数
我们也可以在要增强的方法上加上注解。然后使用@annotation来表示对加了什么注解的方法进行增强。
示例:
首先自定义一个注解,在创建类时选择Annotation

public @interface MyComment{}
注意此时是不能直接用,我们需要添加几个注解
不知道添加什么也很好办,可以直接写一个注解,点击看源码

- @Retention(RetentionPolicy.RUNTIME): 表示注解可以保持到什么时期,RUNTIME就是运行时
- @Target({ElementType.METHOD}): 表示此注解可以添加到哪些东西方法,METHOD就是方法
直接将注解添加到我们自定义的注解上即可

使用自定义注解,直接在相应的方法中添加即可:
此时的切点就不能像之前那样写了,需要使用@annotation注解,并加上自定义注解的全类名

此时运行代码同样可以看到userService中的方法被增强了.

其实这种方式的AOP增强比使用切点表达式灵活多了.
7. 通知
SpingAOP的通知共有五种:
- @Before: 前置通知在方法执行前执行
- @AfterReturning: 返回后通知,在目标方法执行后执行,如果出现异常不会执行
- @After: 后置通知,在目标方法返回结果之后执行,无论是否出现异常都会执行
- @AfterThrowing: 异常通知,在目标方法抛出异常后执行
- @Around: 环绕通知,围绕着方法执行
@Before,@AfterReturning和@After方法使用起来很简单,只需要知道加了这些注解的方法是在什么时候增强的即可
示例:
@Component
@Aspect
public class MyAspect {@Pointcut("@annotation(com.example.aspect.MyComment)")public void point(){}@Before("point()")public void methodBefore(){System.out.println("Before");}@AfterReturning("point()")public void methodAfterReturning(){System.out.println("AfterReturning");}@After("point()")public void methodAfter(){System.out.println("After");}
}
@Service
public class UserService {@MyCommentpublic void update(){System.out.println("执行了UserService的update方法");}
}

注意:@AfterReturning 如果方法中异常不会执行❗
@AfterThrowing恰恰相反,只有出现异常才会执行
在切面类中增加 @AfterThrowing注解的方法
@AfterThrowing("point()")public void methodAfterThrowing(){System.out.println("AfterThrowing");}
让需要增加的方法报错
@Service
public class UserService {@MyCommentpublic void update(){System.out.println("执行了UserService的update方法");System.out.println(1/0);}
}
执行结果:

可以看到没有执行@AfterReturning相应的方法,而是执行了@AfterThrowing相应的方法
以上注解都比较简单,只需要知道他们运行的时机即可,重中之重还是@Around
切面类:
@Component
@Aspect
public class MyAspect {@Pointcut("@annotation(com.example.aspect.MyComment)")public void point(){}@Around("point()")public void methodAround(){System.out.println("Around");}
}
切点
@Service
public class UserService {@MyCommentpublic void update(){System.out.println("执行了UserService的update方法");}
}
运行结果:

虽然执行了@Around相应的方法,但是结果中并没有UserService中的对应的输出语句,这是为什么? 这就是@Around的奇妙之处了
如果想要目标方法执行,需要添加一个ProceedingJoinPoint类型的参数,同时调用里面的proceed()方法:
@Around("point()")
public void methodAround(ProceedingJoinPoint joinPoint){System.out.println("Around");try {joinPoint.proceed();} catch (Throwable e) {throw new RuntimeException(e);}
}
此时就可以正常执行目标方法了

但@Around的用处远不止这些,它可以完成其它4个注解的作用
只需要添加@Around注解的相应方法这么改就可以了.
@Around("point()")public void methodAround(ProceedingJoinPoint joinPoint){System.out.println("方法执行前");try {joinPoint.proceed();System.out.println("方法执行后");} catch (Throwable e) {System.out.println("方法出现异常");throw new RuntimeException(e);}finally {System.out.println("finally进行增强");}}
8. 总结
Spring的AOP基于代理模式实现,它使用代理对象(Proxy)来包装目标对象(Target),从而实现在目标对象的方法执行前、执行后或抛出异常时插入额外的逻辑。可以通过使用注解或配置文件来定义切面和切点,从而将横切关注点应用到目标对象的方法中。
Spring的AOP提供了一系列通知(Advice)类型,如前置通知(Before)、后置通知(After)、环绕通知(Around)、异常通知(AfterThrowing)和最终通知(AfterReturning),可以根据需要选择合适的通知类型来实现特定的横切关注点功能。
相关文章:
【Spring】超详细讲解AOP(面向切面编程)
文章目录 1. 前言2. 什么是AOP3. AOP快速入门4. AOP的核心概念5. 切点表达式6. 切点函数7. 通知8. 总结 1. 前言 本文围绕AOP进行讲解,AOP可以做什么,涉及到了哪些注解,以及各个注解运行的时机,以及Around相较于其它注解有什么不同,并且如果要执行目标方法需要怎么做 2. 什么…...
界面组件DevExpress Reporting v23.1亮点 - 全新升级报表查看器
DevExpress Reporting是.NET Framework下功能完善的报表平台,它附带了易于使用的Visual Studio报表设计器和丰富的报表控件集,包括数据透视表、图表,因此您可以构建无与伦比、信息清晰的报表 界面组件DevExpress Reporting v23.1已经发布一段…...
电容容量换算电池容量,以及RTC持续时间计算
依据 公式1:QI*t 公式2:QC*U 其中: Q: 电荷量 (库仑) I: 电流 (安培) t: 时间 (秒) C: 电容量 (法拉…...
【BIM入门实战】高程点无法放置的解决方法
文章目录 一、问题提出二、解决办法1. 检查模型图形样式2. 高程点可以放置的图元一、问题提出 在平面图中添加高程点时有时会遇到无法在楼板等平面构件上放置高程点,应如何设置才能使高程点正常放置? 如下图所示,楼板上无法放置高程点: 二、解决办法 1. 检查模型图形样式…...
CRM系统对科技企业有哪些帮助
随着国家政策的倾斜和5G等相关基础技术的发展,中国人工智能产业在各方的共同推动下进入爆发式增长阶段,市场发展潜力巨大。CRM客户管理系统作为当下最热门的企业应用,同样市场前景广阔。那么,CRM系统对科技企业有哪些帮助…...
用excel计算一个矩阵的转置矩阵
假设我们的原矩阵是一个3*3的矩阵: 125346789 现在求它的转置矩阵: 鼠标点到一个空白的地方,用来存放结果: 插入-》函数: 选择TRANSPOSE,这个就是求转置矩阵的函数: 点击“继续”:…...
WPF 中的 ControlTemplate 和 DataTemplate 有什么区别
在WPF中,ControlTemplate和DataTemplate都是模板,它们都可以用来定义一段可重复使用的XAML标记。然而,它们的用途和应用场景有很大的不同。 ControlTemplate: ControlTemplate是用来定义控件的外观和视觉行为的。每个WPF控件都有…...
3D重建相关
目录 <font colorblue>整个3D重建的过程是怎样的<font colorblue>体素、网格、点云之间的关系是什么<font colorblue>点云中的颜色怎么处理成最终3D模型上的颜色<font colorblue>点云还原的3D模型的颜色怎么处理,点云有颜色数据?…...
字符串数组排序(Java/JavaScript代码版)
Java public static void main(String[] args) throws Exception {String[] arr new String[] {"abc","xyz","efg"};// 默认按自然升序排Arrays.sort(arr);System.out.println(Arrays.toString(arr)); }降序排 降序排,可传入第二个…...
调用电商集成平台 聚水潭 api接口示例
先上工具类 package com.zuodou.utlis;import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component;import javax.xml.crypto.Data; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import j…...
深入Rust:探索所有权和借用机制
大家好!我是lincyang。 今天,我们将一起深入探索Rust语言中的一个核心概念:所有权和借用机制。 这些特性是Rust区别于其他语言的重要特点,它们在内存管理和并发编程中扮演着关键角色。 一、Rust所有权机制 1. 什么是所有权&#x…...
Python之冒泡排序(AI自动写文章项目测试)
全自动AI生成文章测试,如有不合理地方,请见谅。 一、冒泡排序简介 1.1 冒泡排序概述 冒泡排序(Bubble Sort)是一种简单的排序算法,通过不断交换相邻元素的位置,将最大(或最小)的元…...
spring cloud微服务中多线程下,子线程通过feign调用其它服务,请求头token等丢失
在线程池中,子线程调用其他服务,请求头丢失,token为空的情况 看了很多篇文章的处理方法和在自己亲测的情况下做出说明: 第一种: 这种方式只支持在主线程情况下,能够处理,在多线程情况下&#…...
Nacos 高级玩法:深入探讨分布式配置和服务发现
🎏:你只管努力,剩下的交给时间 🏠 :小破站 Nacos 高级玩法:深入探讨分布式配置和服务发现 前言第一:nacos高级配置管理1. 动态配置的基本使用:2. 监听策略的原理和实现:3…...
CCF CSP认证历年题目自练Day45
这几天搞泰迪杯数据分析技能赛去了。等拿国奖了就出一期关于泰迪杯的。 题目 试题编号: 201703-3 试题名称: Markdown 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 Markdown 是一种很流行的轻量级标记…...
outlook群发邮件
一米群发软件使用Outlook进行群发邮件的步骤如下: 打开Outlook软件,点击页面上方的“新建电子邮件”选项。在弹出的新邮件中,输入收件人和邮件主题,在收件人输入框中输入多个需要接收邮件的邮箱地址,用分号࿰…...
【Attack】针对GNN-based假新闻检测器
Attacking Fake News Detectors via Manipulating News Social Engagement AbstractMotivationContributions FormulationMethodologyAttacker Capability(针对挑战1)Agent Configuration(针对挑战3) WWW’23, April 30-May 4, 20…...
APIcloud 【现已更名 用友开发中心】 iOS发版 应用程序请求用户同意访问相机和照片,但没有在目的字符串中充分说明相机和照片的使用。
iOS 审核时 提示 首次安装软件 获取相机 相册 提示信息 怎么修改 我们注意到你的应用程序请求用户同意访问相机和照片,但没有在目的字符串中充分说明相机和照片的使用。 为了解决这个问题,修改应用信息中的目的字符串是合适的。相机和照片的Plist文件&a…...
记一次弱口令之后引发的获取服务器权限
文章目录 一、漏洞原因二、漏洞成果三、漏洞利用1、管理员权限2、信息泄露3、服务器权限4、数据库权限5、 PHPMyadmin后台管理系统四、总结五、免责声明一、漏洞原因 由于网站登录口未做双因子校验,导致可以通过暴力破解获取管理员账号,成功进入系统;由于未对个人信息进行脱…...
AJAX入门Day01笔记
Day01_Ajax入门 知识点自测 如下对象取值的方式哪个正确? let obj {name: 黑马 }A: obj.a B: obj()a 答案 A选项正确 哪个赋值会让浏览器解析成标签显示? let ul document.querySelector(#ul) let str <span>我是span标签</span>A: ul.innerText str B: ul…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill
视觉语言模型(Vision-Language Models, VLMs),为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展,机器人仍难以胜任复杂的长时程任务(如家具装配),主要受限于人…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...
离线语音识别方案分析
随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...
