【Spring】超详细讲解AOP(面向切面编程)

news2025/1/22 12:37:47

文章目录

  • 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前,大家可能会在每个方法内添加一个输出语句. 但如果类很多,类中的方法也很多,添加起来也很麻烦,而且如果后续要进行修改,也很麻烦

  1. 首先要引入相关依赖:
<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>    
  1. 把相关bean放到Spring容器中

可以使用注解@ComponentScan(basePackages = "com.example"),也可以在xml配置文件中,使用<context:component-scanbase-package="com.example"></context:component-scan>

在这里插入图片描述

因为我的代码结构是这样的,所以是com.example.

  1. 实现AOP

实现AOP可以使用注解,也可以使用xml配置文件. 因为是入门,所以先认识一下注解实现AOP的方式

①开启AOP注解支持

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

②创建切换类

其实就是普通的类,加上@Componentx @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 {
    @MyComment
    public void update(){
        System.out.println("执行了UserService的update方法");
    }
}

在这里插入图片描述
注意:@AfterReturning 如果方法中异常不会执行❗

@AfterThrowing恰恰相反,只有出现异常才会执行

在切面类中增加 @AfterThrowing注解的方法

    @AfterThrowing("point()")
    public void methodAfterThrowing(){
        System.out.println("AfterThrowing");
    }

让需要增加的方法报错

@Service
public class UserService {
    @MyComment
    public 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 {
    @MyComment
    public 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),可以根据需要选择合适的通知类型来实现特定的横切关注点功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1214912.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java实现简单的俄罗斯方块游戏

一、创建新项目 1.首先新建一个项目&#xff0c;并命名为俄罗斯方块。 2.其次新建一个类&#xff0c;命名为Main&#xff0c;或其他的。 二、运行代码 代码如下&#xff1a; package 俄罗斯方块;import java.awt.BorderLayout; import java.awt.Color; import java.awt.Gr…

C# 字节数组按照指定大小拆分保存至TXT文件

1.按照4个字节拆分为一行显示示例代码 byte[] result new byte[] {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 };using (StreamWriter writer new StreamWriter("output.txt")){for (int i 0; i < result.Length; i 4) //按照四个字节拆分{byte[] tempArray n…

Android10 手势导航

种类 Android10 默认的系统导航有三种&#xff1a; 1.两个按钮的 2.三个按钮的 3.手势 它们分别对应三个包名 frameworks/base/packages/overlays/NavigationBarMode2ButtonOverlay frameworks/base/packages/overlays/NavigationBarMode3ButtonOverlay frameworks/base/packa…

【Python3】【力扣题】290. 单词规律

【力扣题】题目描述&#xff1a; 【Python3】代码&#xff1a; 1、解题思路&#xff1a;哈希。两个字典。分别记录字母对应的单词和单词对应的字母&#xff0c;若不是对应的&#xff0c;则返回False。 知识点&#xff1a;字符串.split()&#xff1a;将字符串按指定字符拆分成…

代码随想录算法训练营|五十三天

判断子序列 392. 判断子序列 - 力扣&#xff08;LeetCode&#xff09; 过程&#xff1a; public class Solution {public bool IsSubsequence(string s, string t) {int[,] dp new int[s.Length 1, t.Length 1];for (int i 1; i < s.Length; i) {for (int j 1; j <…

内置升压的单声道D类音频功率放大器:HT81293

HT81293是一款内置升压的单声道D类音频功率放大器&#xff0c;由锂电池供电时&#xff0c; THDN10%&#xff0c; 能连续输出18W功率&#xff08;4Ω负载&#xff09;。 HT81293A内置可动态调节的升压&#xff0c;可以提供一个适应不同输出功率的电压给D类功放&#xff0c;其可大…

1.mysql安装及基础

目录 概述安装上传jar包解压添加用户组和用户更改权限修改配置文件 my.cnf初始化登录mysql修改密码远程登录生效配置 sql语句分类数据定义语言 结束 概述 mysql安装及基础&#xff0c;后续涉及基础会继续补充。 安装 上传jar包 解压 tar -zxvf mysql-5.7.44-linux-glibc2.1…

六、Nacos快速入门

目录 一、服务注册到Nacos 二、nacos服务分级存储模型 1、作用 2、划分集群 3、根据权重负载均衡 三、环境隔离 1、在未设置namespace时&#xff0c;所有服务都默认在public 2、新建namespace 3、将order-service的namespace更改为dev 4、总结 一、服务注册到Nacos …

2019年五一杯数学建模C题科创板拟上市企业估值解题全过程文档及程序

2019年五一杯数学建模 C题 科创板拟上市企业估值 原题再现 科创板在首届中国国际进口博览会开幕式上宣布设立&#xff0c;是独立于现有主板市场的新设板块。设立科创板并试点注册制是提升服务科技创新企业能力、增强市场包容性、强化市场功能的一项资本市场重大改革举措&…

玩转样本量计算,全靠这个在线免费小工具

相信很多小伙伴都有过这样的经历&#xff1a;做科研设计、撰写论文&#xff0c;设计好主题后摆在眼前的是你最头痛的问题——样本量计算。事实上&#xff0c;样本量计算往往是临床医生做临床研究设计的一大障碍&#xff0c;是临床研究设计、临床知识经验以及统计学知识的结合。…

【机器学习】线性回归算法:原理、公式推导、损失函数、似然函数、梯度下降

1. 概念简述 线性回归是通过一个或多个自变量与因变量之间进行建模的回归分析&#xff0c;其特点为一个或多个称为回归系数的模型参数的线性组合。如下图所示&#xff0c;样本点为历史数据&#xff0c;回归曲线要能最贴切的模拟样本点的趋势&#xff0c;将误差降到最小。 2. 线…

第二证券:产业资本真金白银传递市场信心

本年以来&#xff0c;A股商场继续颤抖&#xff0c;但工业本钱纷繁行为&#xff0c;拿出大笔真金白银掀起增持回购潮。Wind数据闪现&#xff0c;到11月15日记者发稿&#xff0c;本年以来已有逾千家公司发布了股票回购预案&#xff0c;拟回购金额上限估计超1200亿元。同期&#x…

《洛谷深入浅出基础篇》P1551亲戚——集合——并查集P1551亲戚

上链接&#xff1a;P1551 亲戚 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P1551 上题干&#xff1a; 题目背景 若某个家族人员过于庞大&#xff0c;要判断两个是否是亲戚&#xff0c;确实还很不容易&#xff0c;现在给出某个亲戚关系图…

LINMP搭建wordpress-数据库不分离

目录 一、nginx部署 1.安装nginx前的系统依赖环境检查 2.下载nginx源代码包 3.解压缩源码包 4.创建普通的nginx用户 5.开始编译安装nginx服务 6.创建一个软连接以供集中管理 7.配置nginx环境变量 二、mysql 1.创建普通mysql用户 2.下载mysql二进制代码包 3.创建mys…

windows的远程桌面服务RDS存在弱加密证书的漏洞处理

背景 漏洞扫描检测windows服务器的远程桌面服务使用了弱加密的ssl证书 思路 按照报告描述&#xff0c;试图使用强加密的新证书更换默认证书 解决 生成证书 通过openssl1.1.1生成&#xff08;linux自带openssl&#xff0c;windows安装的是openssl1.1.1w&#xff09;&#x…

基于Vue+SpringBoot的农村物流配送系统 开源项目

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 系统登录、注册界面2.2 系统功能2.2.1 快递信息管理&#xff1a;2.2.2 位置信息管理&#xff1a;2.2.3 配送人员分配&#xff1a;2.2.4 路线规划&#xff1a;2.2.5 个人中心&#xff1a;2.2.6 退换快递处理&#xff1a;…

智能电网短路故障接地故障模拟柜

智能电网短路故障接地故障模拟柜是一种用于模拟智能电网中短路故障和接地故障的设备&#xff0c;它可以模拟电网中的各种故障情况&#xff0c;帮助电力工程师进行故障诊断和维修。智能电网中的短路故障是指电路中出现了异常的电流路径&#xff0c;导致电流过大&#xff0c;可能…

利用ffmpeg实现rtmp和rtsp推流

环境说明 windows11 : ffmpeg VLC Linux Unbuntu20.04 : SRS MediaMTX 可选&#xff1a;GStreamer win11下载ffmpeg和ffplay ffmpeg官网 添加环境变量&#xff1a;添加ffmpeg/bin所在的路径。 D:\ffmpeg\ffmpeg-master-latest-win64-lgpl-shared\bin win11查看本机电脑的设备…

基于单片机的水位检测系统仿真设计

**单片机设计介绍&#xff0c; 基于单片机的水位检测系统仿真设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机的水位检测系统仿真系统是一种用于模拟水位检测系统的工作过程&#xff0c;以验证设计方案的可行性和优…

赢麻了……腾讯1面核心9问,小伙伴过了提42W offer

说在前面 在40岁老架构师尼恩的&#xff08;50&#xff09;读者社群中&#xff0c;经常有小伙伴&#xff0c;需要面试腾讯、美团、京东、阿里、 百度、头条等大厂。 下面是一个小伙伴成功拿到通过了腾讯面试&#xff0c;并且最终拿到offer&#xff0c;一毕业就年薪42W&#x…