当前位置: 首页 > news >正文

Spring AOP —— 详解、实现原理、简单demo

目录

一、Spring AOP 是什么?

二、学习AOP 有什么作用?

三、AOP 的组成

3.1、切面(Aspect)

3.2、切点(Pointcut)

3.3、通知(Advice)

3.4、连接点

四、实现 Spring AOP 一个简单demo

4.1、添加 Spring AOP  框架依赖

4.2、定义切面

4.3、定义切点

4.3.1、切点表达式说明

4.4、定义通知

4.5、实现原理

​编辑  

五、Spring AOP 实现原理

5.1、原理概述

5.2、织入

5.3、动态代理

5.4、面试题:DK 和 CGLIB 实现的区别


一、Spring AOP 是什么?


AOP 就是面向切面的编程, 是一种思想,是对某一类事情的集中处理。

例如登陆权限的检验(检测当前用户是否登录),在学习 AOP 前,我们会将这样一个检测机制封装成一个方法,在需要检测的地方调用该方法即可,但想象以下,首先,如果这个方法有 1000 个地方要进行调用, 那么你去一个一个写调用函数很累,其次,一旦这个登陆检查方法需要修改,比如增加一个参数,那么,你就需要修改 1000 方法调用的参数... 但如果你会 AOP 后,我们只需要在某处配置一下,就可以实现用户的登录检测,不需要每一个方法中都写登录检验的调用方法啦! 

AOP 是一种思想,而 Spring AOP 是一个框架,提供了对 AOP 思想的实现(类似于 IoC 和 DI 的关系)。

二、学习AOP 有什么作用?


例如刚刚我们所讲到的登录检测机制,这一个方法一旦需要调用的地方多了,不仅写起来麻烦,维护起来成本也是很高的,所以,对于这种功能统一,且使用地方较多的功能,就可以考虑 AOP 来进行统一的处理!

例如以下常见的使用场景:

  • 统一登录检测机制。
  • 统一方法的执行时间统计。
  • 统一的返回格式设置。
  • 统一异常处理。
  • 事务的开始和提交。

Ps: AOP 是对某一功能进行的统一处理,大大降低了代码维护的成本,所以可以说 AOP 是 OOP 的补充和完善~

三、AOP 的组成


3.1、切面(Aspect)

切面,在程序中就是对某一功能进行统一处理的, 这个类里包含了很多方法,这些方法就是由 切点通知 组成。

3.2、切点(Pointcut)

用来进行主动拦截的规则(配置)。

这里拦截的是什么,过程是什么样的呢?就是对用户向服务器发送的请求进行拦截,检测用户的操作是否符合预期,发现问题并统一处理的过程,如下图:

 

3.3、通知(Advice)

通知就是 AOP 的具体执行动作。具体的,在程序中被拦截后会触发一个具体的动作,就是通知中具体实现的业务代码

在 Spring 中,可以在方法上使用以注解,设置方法为通知方法,被拦截后满足条件就会调用通知方法:

  • 前置通知(@Before):执行 目标方法(被拦截的方法)之前执行的方法。
  • 后置通知(@After):执行了目标方法之后执行的方法。
  • 返回之后通知(@AfterReturning):目标方法执行了返回数据(return)时,执行的方法。
  • 抛异常后通知(@AfterThrowing):在执行目标方法出现异常时,执行的方法。
  • 环绕通知(@Around):在目标方法执行的周期范围内(执行之前,执行中,执行后)都可以执行的方法(Ps:如果已经有了前置和后置通知,再使用环绕通知,那么周期范围就在前置通知之前 ~ 后置通知之后)。

3.4、连接点

会触发 AOP 规则的所有的点(所以请求)。

四、实现 Spring AOP 一个简单demo


4.1、添加 Spring AOP  框架依赖

		<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>

Ps:

1.创建 Spring Boot 项目时是没有 Spring AOP 框架可以选择的。

2.添加  Spring AOP 框架可以去中央仓库,值得注意的是要选择 Spring Boot 对应的 AOP ,而不是 Spring 对应的 AOP。

3.最好选择 Spring Boot 对应版本的  AOP ,以上就是 2.7.9版本。

4.2、定义切面

使用 @Aspect 注解修饰类,告诉框架是一个切面类。

import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.stereotype.Component;@Aspect //告诉框架我是一个切面类
@Component
public class UserAspect {}

4.3、定义切点

使用 @Pointcut 修饰一个方法,它不需要由方法体。方法名就是起到一个标识的作用,标识通知方法具体指的是哪一个切点(切点可能有多个)。

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect //告诉框架我是一个切面类
@Component
public class UserAspect {/*** 切点:配置拦截规则*/@Pointcut("execution(* com.example.demo.controller.UserController.*(..))")public void pointcut() {}}

4.3.1、切点表达式说明

AspectJ ⽀持三种通配符,如下:

  • * :匹配任意字符,只匹配⼀个元素(包,类,或⽅法,⽅法参数)
  • .. :匹配任意字符,可以匹配多个元素 ,在表示类时,必须和 * 联合使⽤。
  • + :表示按照类型匹配指定类的所有类,必须跟在类名后⾯,如 com.cad.Car+ ,表示继承该类的 所有⼦类包括本身

切点表达式由切点函数组成,其中 execution() 是最常⽤的切点函数,⽤来匹配⽅法,语法如下(注意使用空格进行分割):

execution(<修饰符> <返回类型> <包.类.⽅法(参数)> <异常>)

其中,修饰符和异常可以省略,具体含义如下:

 

4.4、定义通知

使用通知方法中的五个注解,其中前置通知、后置通知、环绕通知最常用,那么以下代码我将用这三个注解来举例:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect //告诉框架我是一个切面类
@Component
public class UserAspect {/*** 切点:配置拦截规则*/@Pointcut("execution(* com.example.demo.controller.UserController.*(..))")public void pointcut() {}/*** 前置通知*/@Before("pointcut()")public void beforeAdvice() {System.out.println("执行了前置通知");}/*** 后置通知*/@After("pointcut()")public void aftereAdvice() {System.out.println("执行了后置通知");}/*** 环绕通知* @param joinPoint* @return* @throws Throwable*/@Around("pointcut()")public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("进入了环绕通知~");Object obj = null;obj = joinPoint.proceed();System.out.println("退出了环绕通知~");return obj;}}

执行结果如下:

4.5、实现原理

  

五、Spring AOP 实现原理


5.1、原理概述

Spring 的切面是代理类实现的,包裹了目标对象,也就是说,用户只能先通过代理类,进行校验,如果没有问题才会进一步访问到目标对象。

5.2、织入

织入简单理解就是代理生成的时机,一般情况下,在 Spring AOP 动态代理的植入时机是程序的运行期。

5.3、动态代理

Spring AOP 是建立在动态代理的基础上,因此 Spring 对 AOP 的支持局限于方法级别的拦截。

Spring AOP 支持 JDK Proxy 和 CGLIB 方式实现动态代理。默认情况下,实现了接口的类,使用 AOP 会基于 JDK 生成代理类,没有实现接口的类,会基于 CGLIB 生成代理类。

JDK 和 CGLIB 底层都是基于反射实现的。、

5.4、面试题:DK 和 CGLIB 实现的区别

1. JDK 实现,要求被代理类必须实现接⼝,之后是通过 InvocationHandler 及 Proxy,在运⾏ 时动态的在内存中⽣成了代理类对象,该代理对象是通过实现同样的接⼝实现(类似静态代理接⼝实现的⽅式),只是该代理类是在运⾏期时,动态的织⼊统⼀的业务逻辑字节码来完成。

2. CGLIB 实现,被代理类可以不实现接⼝,是通过继承被代理类,在运⾏时动态的⽣成代理类对象。

相关文章:

Spring AOP —— 详解、实现原理、简单demo

目录 一、Spring AOP 是什么&#xff1f; 二、学习AOP 有什么作用&#xff1f; 三、AOP 的组成 3.1、切面&#xff08;Aspect&#xff09; 3.2、切点&#xff08;Pointcut&#xff09; 3.3、通知&#xff08;Advice&#xff09; 3.4、连接点 四、实现 Spring AOP 一个简…...

(蓝桥真题)异或数列(博弈)

题目链接&#xff1a;P8743 [蓝桥杯 2021 省 A] 异或数列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 样例输入&#xff1a; 4 1 1 1 0 2 2 1 7 992438 1006399 781139 985280 4729 872779 563580 样例输出&#xff1a; 1 0 1 1 分析&#xff1a;容易想到对于异或最大值…...

4万字数字政府建设总体规划方案WORD

本资料来源公开网络&#xff0c;仅供个人学习&#xff0c;请勿商用。部分资料内容&#xff1a; 我省“数字政府”架构 &#xff08;一&#xff09; 总体架构。 “数字政府”总体架构包括管理架构、业务架构、技术架构。其中&#xff0c;管理架构体现“管运分离”的建设运营模式…...

CCF/CSP 201709-2公共钥匙盒100分

试题编号&#xff1a;201709-2试题名称&#xff1a;公共钥匙盒时间限制&#xff1a;1.0s内存限制&#xff1a;256.0MB问题描述&#xff1a;问题描述  有一个学校的老师共用N个教室&#xff0c;按照规定&#xff0c;所有的钥匙都必须放在公共钥匙盒里&#xff0c;老师不能带钥…...

【OC】Blocks模式

1. Block语法 Block语法完整形式如下&#xff1a; ^void (int event) {printf("buttonId:%d event%d\n", i, event); }完整形式的Block语法与一般的C语言函数定义相比&#xff0c;仅有两点不同。 没有函数名。带有“^”&#xff08;插入记号&#xff09;。 因为O…...

软件设计师教程(七)计算机系统知识-操作系统知识

软件设计师教程 软件设计师教程&#xff08;一&#xff09;计算机系统知识-计算机系统基础知识 软件设计师教程&#xff08;二&#xff09;计算机系统知识-计算机体系结构 软件设计师教程&#xff08;三&#xff09;计算机系统知识-计算机体系结构 软件设计师教程&#xff08;…...

蓝桥杯2023/3/2

1. 小蓝正在学习一门神奇的语言&#xff0c;这门语言中的单词都是由小写英文字母组 成&#xff0c;有些单词很长&#xff0c;远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词&#xff0c;他准备不再完全记忆这些单词&#xff0c;而是根据单词中哪个字母出现得最…...

【IoT】创业成功不可或缺的两个因素:能力和趋势

今天就来谈谈能力和趋势究竟哪个更重要的问题。 在谈成功的十大要素时&#xff0c;我曾经讲到&#xff1a; 一命、二运、三风水&#xff0c;这三个要素几乎不涉及任何个人的努力。 而趋势跟这三个要素又是息息相关的&#xff0c;这也类似雷军所说的飞猪理论。 只要风足够大&…...

2020蓝桥杯真题日期格式 C语言/C++

问题描述 小蓝要处理非常多的数据, 其中有一些数据是日期。 在小蓝处理的日期中有两种常用的形式: 英文形式和数字形式。 英文形式采用每个月的英文的前三个宁母作为月份标识, 后面跟两位数字 表示日期, 月份标识第一个字母大写, 后两个字母小写, 日期小于 10 时要补 前导 0s…...

总时差与自由时差

定义总时差&#xff08;总浮动时间&#xff09;&#xff08;TF&#xff0c;Total Free Time&#xff0c;不耽误项目总进度&#xff09;LS&#xff08;Latest Start&#xff09;-ES&#xff08;Earliest Start&#xff09;LF&#xff08;Latest Finish&#xff09;-EF&#xff0…...

LeetCode两个数组的交集-跳跃游戏- 最长有效括号

两个数组的交集 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,2,1], nums2 [2,2] 输出&#xff1a;[2] 示例 2&#xff1a; 输入&…...

mysql普通索引与唯一索引怎么选择

学习mysql普通索引与唯一索引选择记录总结&#xff0c;学习链接&#xff1a;http://gk.link/a/11YG8从mysql查询操作分析&#xff1a;普通索引&#xff1a;查到满足条件的第一条记录后&#xff0c;还会继续查找下一条记录&#xff0c;直到出现满足条件的记录出现后停止检索唯一…...

JavaWeb开发(三)3.5——Java的反射机制

一、反射机制的概念 指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法&#xff0c;对于任意一个对象&#xff0c;都能调用它的任意一个方法。这种动态获取信息&#xff0c;及动态调用对象方法的功能叫java语言的反射机制。 Java反射机制的核心是在程序运行时动…...

Python每日一练(20230305)

目录 1. 正则表达式匹配 ★★★ 2. 寻找旋转排序数组中的最小值 II ★★★ 3. 删除排序链表中的重复元素 II ★★ 1. 正则表达式匹配 给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符* 匹配零个或多个…...

SpringBoot三种方法实现定时发送邮件的案例

前言 小编我将用CSDN记录软件开发之路上所学的心得与知识&#xff0c;有兴趣的小伙伴可以关注一下&#xff01;也许一个人独行&#xff0c;可以走的很快&#xff0c;但是一群人结伴而行&#xff0c;才能走的更远&#xff01;让我们在成长的道路上互相学习&#xff0c;让我们共…...

opengl、opengl es、webgl介绍与opengl开发入门

1、OpenGL OpenGL&#xff08;英语&#xff1a;Open Graphics Library&#xff0c;译名&#xff1a;开放图形库或者“开放式图形库”&#xff09;常用于CAD、虚拟现实、科学可视化程序和电子游戏开发。OpenGL的高效实现&#xff08;利用了图形加速硬件&#xff09;存在于Windo…...

Vue3之组件间传值

何为组件间传值 在Vue3之组件文章中&#xff0c;我们学会了定义使用组件&#xff0c;但是我们似乎还缺少什么将组件之间联系起来&#xff0c;说到组件之间的联系就不得不提组件间的传值&#xff0c;而组件间的传值其实也不难理解&#xff0c;就是如何在子组件中接收到父组件传…...

Windows10下使用CMake编译ITK5.2.1步骤

编译环境&#xff1a;Windows10VS2017Cmak3.24.0ITK5.2.1 编译步骤&#xff1a; 1、下载ITK到本地&#xff1a;ITK官网Download | ITK&#xff0c;ITK5.2.1下载地址 https://github.com/InsightSoftwareConsortium/ITK/releases/download/v5.2.1/InsightToolkit-5.2.1.zip ​…...

字符串模式匹配,经典KMP算法你还不会?我可不允许你不会!

文章目录重点1. 简单模式匹配算法2. 部分匹配值PM的算法&#xff08;Move j-1 PM[j-1]&#xff09;3. 部分匹配值PM的两次改进&#xff08;Move j-next[j]&#xff09;4. 快速得到next数组5. KMP匹配算法重点 童鞋们看网上讲解的时候一定要分清楚序列是从0开始还是从1开始&…...

C++操作redis(实现连接池、分布式锁)

文章目录Redis连接池编译项目整体架构使用分布式锁总结Redis连接池 封装hiredis的一些基本操作&#xff0c;redishelper类提供包含连接&#xff0c;放回&#xff0c;存取键&#xff0c;push&#xff0c;pop&#xff0c;执行redis语句和执行lua脚本的函数&#xff0c;连接池是类…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能&#xff0c;我们需要对它的功能特点进行分析&#xff1a; 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具&#xff1a; mysql&#xff1a;关系型数据库&am…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

OD 算法题 B卷【正整数到Excel编号之间的转换】

文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的&#xff1a;a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...

数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !

我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...

智能职业发展系统:AI驱动的职业规划平台技术解析

智能职业发展系统&#xff1a;AI驱动的职业规划平台技术解析 引言&#xff1a;数字时代的职业革命 在当今瞬息万变的就业市场中&#xff0c;传统的职业规划方法已无法满足个人和企业的需求。据统计&#xff0c;全球每年有超过2亿人面临职业转型困境&#xff0c;而企业也因此遭…...

webpack面试题

面试题&#xff1a;webpack介绍和简单使用 一、webpack&#xff08;模块化打包工具&#xff09;1. webpack是把项目当作一个整体&#xff0c;通过给定的一个主文件&#xff0c;webpack将从这个主文件开始找到你项目当中的所有依赖文件&#xff0c;使用loaders来处理它们&#x…...

CppCon 2015 学习:REFLECTION TECHNIQUES IN C++

关于 Reflection&#xff08;反射&#xff09; 这个概念&#xff0c;总结一下&#xff1a; Reflection&#xff08;反射&#xff09;是什么&#xff1f; 反射是对类型的自我检查能力&#xff08;Introspection&#xff09; 可以查看类的成员变量、成员函数等信息。反射允许枚…...