【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…...

spring boot 环境变量问题
org.yaml.snakeyaml.scanner.ScannerException: while scanning for the next token found character that cannot start any token. (Do not use for indentation) in reader, line 4, column 13: active: spring.profiles.active 添加 以下依赖即可 <!-- 解决环…...

Javaweb开发 利用servlet+jsp+jdbc+tomcat数据库实现登录功能
前言:很久没更新了,今天给大家分享一个Java web的小案例,是一个登录页面,利用Login控制类和JDBC连接数据库,并判断用户名密码是否正确,项目最终部署在Tomcat上。 先看效果 正文 一、前期工作 1.首先我们…...

flutter下拉列表
下拉列表 内容和下拉列表的标题均可滑动 Expanded: 内容限制组件,将其子类中的无限扩展的界面限制在一定范围中。在此使用,是为了防止下拉列表中的内容超过了屏幕限制。 SingleChildScrollView: 这个组件,从名字中可…...

ElastaticSearch -- es深度分页 searchAfter
searchAfter深度分页 es一次只能查1万条数据,如果超过1万,会报错如下: "reason": {"type": "query_phase_execution_exception","reason": "Result window is too large, from size must be …...

【2021集创赛】Arm杯二等奖-基于Arm核的智慧病房手势识别方案
团队介绍 参赛单位:上海交通大学 队伍名称:芯灵手巧 指导老师:王琴、景乃锋 参赛队员:林圣凯、林新源、莫志文 总决赛奖项:二等奖 1.项目概述 1.1 选题背景 我们的选题背景是考虑到很多卧床病人不便于独自向医护人…...

通过注解统计接口调用耗时
要通过注解统计接口调用耗时,可以按照以下步骤进行操作: 首先,在您的项目中引入一个AOP(面向切面编程)框架,比如Spring AOP或AspectJ。这些框架可以帮助您在方法执行前后插入额外的逻辑。 创建一个自定义的…...

Oracle-动态sql学习笔记,由易至难讲解七个例子
本文章的内容来源于对oracle课堂上讲的内容做出的笔记 静态sql和动态sql 静态sql: 静态 SQL 是在编译时写死的 SQL 语句,即在程序编写阶段,SQL 语句已经被固定下来。 特点: 1.预编译: SQL 语句在程序编译时就会被…...

Kafka 的应用场景
Kafka 是一个开源的分布式流式平台,它可以处理大量的实时数据,并提供高吞吐量,低延迟,高可靠性和高可扩展性。 Kafka 最初是为分布式系统中海量日志处理而设计的。它可以通过持久化功能将消息保存到磁盘,并让消费者按…...

保驾“双十一” 博睿数据助力电商零售迎高峰无烦忧
如果说“双十一”大战的A面是由天猫、京东、拼多多、唯品会等电商平台,以及一些MCN机构、头部主播拉动的一系列购物狂潮,那么B面则是零售、物流、制造、银行保险等全产业链面对海量流量之下,以强大的心力、脑力与体力应对流量增加和交易陡增的…...

F.binary_cross_entropy、nn.BCELoss、nn.BCEWithLogitsLoss与F.kl_div函数详细解读
提示:有关loss损失函数详细解读,并附源码!!! 文章目录 前言一、F.binary_cross_entropy()函数解读1.函数表达2.函数运用 二、nn.BCELoss()函数解读1.函数表达2.函数运用 三、nn.BCEWithLogitsLoss()函数解读1.函数表达…...