Spring AOP:什么是AOP? 为什么要用AOP?如何学习AOP?

文章目录

  • 🎆前言
  • 1.为什么要用 AOP
  • 3.如何学习去 AOP?
    • 3.1 AOP 的组成
      • 切面(Aspect)
      • 连接点(Join Point)
      • 切点(Pointcut)
      • 通知(Advice)
  • 3. Spring AOP 实现
    • 3.1 普通的方式实现 AOP
    • 3.2 通过 @annotation 切断函数实现 AOP
    • 3.3 获取增强方法相关信息

🎆前言

学习一件新知识,我们首先要先了解它的概念;AOP(Aspect Oriented Programming):面向切面编程,它是⼀种思想,它是对某⼀类事情的集中处理。比如用户登录权限的校验,没有 AOP 之前,我们在所有需要判断用户登录的页面都进行调用用户验证的方法,而有了 AOP 之后,我们只需在一处配置好 AOP 规则,需要判断用户登录页面(还要接口)全部可以实现自主的登录验证,不再需要每次调用验证登录的方法,不但解决了每次调用验证方法的问题,还降低了代码的耦合性。
通俗的说,AOP就像一张网,会对某一个过程进行筛选,通过筛选的才能进行规定的操作,不通过的则会按照不通过的规则操作。
当然 AOP 是一种思想,而 Spring AOP 是一个框架,提供了 这个思想的实现方式。

1.为什么要用 AOP

还举上方那个例子,我们在处理用户登录验证时,每次验证都需要调用处理方法,随着我们项目的功能越来越多,而这些方法又相同,这么多的方法就会在代码修改和维护上使成本变高,对于这个问题,我们的处理方案就是:对功能统一的,且使用的地方较多的功能,就考虑使用 AOP 来统一处理。

AOP 可以实现的统一处理如下:

  • 统一日志记录
  • 统一方法执行时间统计
  • 统一返回格式设置
  • 统一的异常处理
  • 事务的开启和提交等

也就是说使⽤ AOP 可以扩充多个对象的某个能⼒,所以 AOP 可以说是 OOP(Object Oriented Programming,⾯向对象编程)的补充和完善。

3.如何学习去 AOP?

Spring AOP 学习主要分为以下 3 个部分:

  1. 学习 AOP 是如何组成的?也就是学习 AOP 组成的相关概念。
  2. 学习 Spring AOP 使⽤。
  3. 学习 Spring AOP 实现原理。

3.1 AOP 的组成

切面(Aspect)

切⾯(Aspect)由切点(Pointcut)和通知(Advice)组成,它既包含了横切逻辑的定义,也包括了连接点的定义。通俗的说切面就是一个处理某个方面具体问题的类,类里包含了很多方法,这些方法就是通知、切点。

连接点(Join Point)

应⽤执行过程中能够插⼊切面的⼀个点,这个点可以是⽅法调⽤时,抛出异常时,甚⾄修改字段时。切⾯代码可以利⽤这些点插⼊到应⽤的正常流程之中,并添加新的行为。

切点(Pointcut)

切点 的作⽤就是提供⼀组规则(使⽤ AspectJ pointcut expression language 来描述)来匹配连接点,给满足规则的连接点添加通知。

通知(Advice)

切⾯也是有⽬标的 ——它必须完成的⼯作。在 AOP 术语中,切⾯的⼯作被称之为通知。
通知:程序被拦截请求触发后的具体动作。

Spring 切面类中,可以在方法上使用一下注解,去设置方法为通知方法,在满足条件后会通知本方法进行调用:

  • 前置通知使⽤ @Before:通知方法会在目标方法调用之前执行。
  • 后置通知使⽤ @After:通知⽅法会在⽬标⽅法返回或者抛出异常后调⽤。
  • 返回之后通知使⽤ @AfterReturning:通知⽅法会在目标方法返回后调⽤。
  • 抛异常后通知使⽤ @AfterThrowing:通知⽅法会在⽬标⽅法抛出异常后调⽤。
  • 环绕通知使⽤ @Around:通知包裹了被通知的⽅法,在被通知的⽅法通知之前和调⽤之后执行自定义的行为。

AOP 整个组成部分的概念如下图所示,以多个⻚⾯都要访问⽤户登录权限为例:
没有使用AOP前,我们不调用登录验证方法,他就不会对用户登录进行验证,使用AOP后,当用户要使用某个需要登陆才有的功能时,AOP 就是根据配置好的文件自动验证是否登陆。
在这里插入图片描述

3. Spring AOP 实现

3.1 普通的方式实现 AOP

使用Spring AOP 来实现⼀下 AOP 的功能,完成的⽬标是拦截所有 UserController 里面的⽅法,每次调⽤ UserController 中任意⼀个⽅法时,都执⾏相应的通知事件。

Spring AOP 的实现步骤如下:

  1. 添加 Spring AOP 框架⽀持。
<!-- springboot-aop 技术 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  1. 定义切面(创建切面类)
@Slf4j
@Component
@Aspect
public class MYAspect {@Pointcut("execution(* com.example.demo.controller.*.*(..))")public void put() {}@Before("put()")public void before() {log.error("方法被调用了");}
}
  1. 定义切点(配置拦截规则)
    写法:execution([修饰符] 返回类型 包名.类名.方法名(参数))
  • 修饰符:访问修饰符可以省略,大部分情况下省略
  • 返回类型:返回值类型、包名、类名、方法名可以使用星号 * 代表任意
  • 包名、类名:包名与类名之间一个点 代表当前包下的类,两个点代表当前包及齐子包下的类
  • 方法名(参数):参数列表可以使用两个点 表示任意个数,任意类型的参数列表
execution(* com.zzq.service.*.*(..)) // 表示com.zzq.service 包下任意类,方法名任意,参数列表任意,返回值类型任意
execution(* com.zzq.service.*..*(..)) // 表示 com.zzq.service 包及其子包下任意类,方法名任意,参数列表任意,返回值类型任意
execution(* com.zzq.service.*.*())   // 表示 com.zzq.service 包下任意类,方法名任意,要求方法不能有参数,返回值类型任意
execution(* com.zzq.service.*.delete*(..)) // 表示 com.zzq.service 包下任意类,要求方法不能有参数,返回值类型任意,方法名要求以 delete 开头 
  1. 定义通知
    @Before("put()")public void before() {log.error("方法被调用了");}

当我们调用 com.example.demo.controller 中的方法时,就会先执行通知里面的东西,再执行方法,如下图(这里为了能看的更清楚,我们用了日子打印信息)
在这里插入图片描述

3.2 通过 @annotation 切断函数实现 AOP

  1. 定义切面类
@Slf4j
@Component
@Aspect
public class MYAspect {@Pointcut("@annotation(com.example.demo.aspect.InvokeLog)")public void put() {}@Before("put()")public void before() {log.error("方法被调用了");}
}
  1. 定义切点
    切点函数扫描位置是我们下面定义注解的位置
 @Pointcut("@annotation(com.example.demo.aspect.InvokeLog)")public void put() {}
  1. 定义通知
    @Before("put()")public void before() {log.error("方法被调用了");}
  1. 实现注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface InvokeLog {
}

那个方法需要增强时,我们就在这个方法上面加上这个注解,如下图:
在这里插入图片描述
加过注解的方法,就会得到增强,也就是执行通知里面的代码,如下图:
在这里插入图片描述

3.3 获取增强方法相关信息

我们是在通知的参数列表当中添加一个参数 JoinPoint joinPoint 这个参数可以帮我们拿到被增强方法相关的数据

@Before("put()")public void before(JoinPoint joinPoint) {Object[] args = joinPoint.getArgs(); // 获取参数列表中的参数Object target = joinPoint.getTarget(); // 获取代理对象MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // 获取被增强的方法签名封装的对象Method method = signature.getMethod(); // 获取被增强的方法log.error("方法被调用了");}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++设计模式之策略模式

策略模式 介绍示例示例测试运行结果应用场景优点总结 介绍 策略模式是一种行为设计模式。在策略模式中&#xff0c;可以创建一些独立的类来封装不同的算法&#xff0c;每一个类封装一个具体的算法&#xff0c;每一个封装算法的类叫做策略(Strategy)&#xff0c;为了保证这些策…

2.19 keil里面工具EventCorder使用方法

设置方法如下&#xff1a; 添加初始化代码如下&#xff1a; eventRecord.c #include "eventRecord.h" #include "usart.h" extern UART_HandleTypeDef *pcControlUart;/* RecordEvent初始化 */ void InitEventRecorder(void) {#ifdef RTE_Compiler_Even…

【Kotlin精简】第9章 Kotlin Flow

1 前言 上一章节我们学习了Kotlin的协程【Kotlin精简】第8章 协程&#xff0c;我们知道 协程实质是对线程切换的封装&#xff0c;能更加安全实现异步代码同步化&#xff0c;本质上协程、线程都是服务于并发场景下&#xff0c;其中协程是协作式任务&#xff0c;线程是抢占式任务…

Java开发环境配置“JDK”超详细整理,适合新手入门

目录 一、什么是JDK&#xff1f; 二、Java中JDK8、JDK17该怎么选择&#xff1f; 三、JDK和JRE是什么关系&#xff1f; 四、JDK包含的基本组件 五、JDK下载步骤 JDK 安装 1、双击运行安装包&#xff0c;出现安装程序&#xff0c;点击下一步 2、修改JDK安装目录 3、根据…

【Django-DRF】md笔记第6篇:Django-DRF的视图、认证、分页和其他功能详解

本文从分析现在流行的前后端分离Web应用模式说起&#xff0c;然后介绍如何设计REST API&#xff0c;通过使用Django来实现一个REST API为例&#xff0c;明确后端开发REST API要做的最核心工作&#xff0c;然后介绍Django REST framework能帮助我们简化开发REST API的工作。 DR…

算法-中等-链表-两数相加

记录一下算法题的学习11 两数相加 题目&#xff1a;给你两个非空的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照逆序的方式存储的&#xff0c;并且每个节点只能存储一位数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字…

Linux:Ubuntu系统安装软件

本次以安装vim为例 sudo apt-get remove vim //卸载vim sudo apt-get install vim //安装vim sudo apt-cache show vim //获取vim软件信息安装时间较长。 安装完成后&#xff0c;执行下第三条指令&#xff0c;测试下是否安装成功即可。

01、Tensorflow实现二元手写数字识别

01、Tensorflow实现二元手写数字识别&#xff08;二分类问题&#xff09; 开始学习机器学习啦&#xff0c;已经把吴恩达的课全部刷完了&#xff0c;现在开始熟悉一下复现代码。对这个手写数字实部比较感兴趣&#xff0c;作为入门的素材非常合适。 基于Tensorflow 2.10.0 1、…

Java--类和对象

目录 面向对象一.类1.类的创建默认初始化2.类的实例化3.注意事项利用类的创建来交换值 二.this1.使用this2.可使用this来调用其他构造方法来简化 三.构造方法3.1概念3.2特性3.3不带参数的构造方法3.4带参数的构造方法当使用自定义的构造方法后&#xff0c;再删除时&#xff0c;…

数据结构-树-二叉树-堆的实现

1.树概念及结构 树是一种 非线性 的数据结构&#xff0c;它是由 n &#xff08; n>0 &#xff09;个有限结点组成一个具有层次关系的集合。 把它叫做树是因 为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的 。 有一个特殊的结点&#xff…

【数据结构 —— 堆的实现(顺序表)】

数据结构 —— 堆的实现&#xff08;顺序表&#xff09; 一.堆1.1堆的定义及结构1.1.1.堆的定义1.1.2.堆的性质1.1.3.堆的结构 二.堆的实现2.1.头文件的实现 —— &#xff08;Heap.h&#xff09;2.2.源文件的实现 —— &#xff08;Heap.c&#xff09;2.2.1.小堆的源文件2.2.2…

leetcode:随机链表的复制

题目描述 题目链接&#xff1a;138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 题目分析 这个题目很长&#xff0c;但是意思其实很简单&#xff1a;就是一个单链表&#xff0c;每个结点多了一个指针random随机指向链表中的任意结点或者NULL&#xff0c;我们血需…