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

Spring AOP基于注解方式实现和细节

目录

一、Spring AOP底层技术

二、初步实现AOP编程

三、获取切点详细信息

四、 切点表达式语法

五、重用(提取)切点表达式


一、Spring AOP底层技术

SpringAop的核心在于动态代理,那么在SpringAop的底层的技术是依靠了什么技术呢?

  • 动态代理(InvocationHandler):JDK原生的实现方式,需要被代理的目标类必须实现接口。因为这个技术要求代理对象和目标对象实现同样的接口(兄弟两个拜把子模式)。
  • cglib:通过继承被代理的目标类实现代理,所以不需要目标类实现接口。
  • AspectJ:早期的AOP实现的框架,SpringAOP借用了AspectJ中的AOP注解。

二、初步实现AOP编程

2.1实现AOP需要以下注解:

注解说明
@SpringJUnitConfig在JUnit测试类中使用Spring测试上下文配置
@Aspect将类标记为切面类,定义切面逻辑和增强方法的位置
@EnableAspectJAutoProxy开启AspectJ自动代理,用于启用Spring AOP的功能

2.2需要导入以下依赖

<!-- 切面实现 --><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>6.0.6</version>
</dependency>
<!-- spring核心 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.0.2.RELEASE</version></dependency>
<!-- spring-test容器测试 --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>6.0.6</version><scope>test</scope></dependency>

2.3 增强(通知)注解

注解说明
@Before在目标方法执行前执行的增强逻辑
@AfterReturning在目标方法成功返回后执行的增强逻辑
@AfterThrowing在目标方法抛出异常后执行的增强逻辑
@After在目标方法执行后执行的增强逻辑
@Around包裹目标方法,在目标方法执行前后都可以执行自定义的增强逻辑

实现增强(通知)的步骤

  1. 定义方法存储增强代码
  2. 使用注解配置,指定插入目标的位置
  3. 配置切点表达式(选中插入的方法,切点)
  4. 补全注解,加入到ioc容器,并且设置切面@Aspect
  5. 开启Aspect注解注释

案例代码:

//4.补全注解
@Component
@Aspect//1.创建增强类与增强方法start(),after,Error
public class advice {//    2.使用注解配置,配置插入位置@Before @After @AfterThrowing
//    3.配入切点表达式execution(* com.alphamilk.Impl.*.*(..))表明需要插入的方法为所有com.alhpamilk.Impl包下所有类的所有方法@Before("execution(* com.alphamilk.Impl.*.*(..))")public void  start(){System.out.println("方法起始处插入");}@After("execution(* com.alphamilk.Impl.*.*(..))")public void after(){System.out.println("方法结束后插入");}@AfterThrowing("execution(* com.alphamilk.Impl.*.*(..))")public void Error(){System.out.println("方法异常时候插入");}
}
@ComponentScan(value = "com.alphamilk")
@Configuration
//6.注解类中开启注解注释
@EnableAspectJAutoProxy
public class JavaConfig {
}


三、获取切点详细信息

虽然已经初步实现了AOP的实现,但是还不够,在调用多个方法时候如果都是输入,调用方法前,调用方法后等等,这样并不能区分是调用了哪个方法,所以为了区分我们需要获取调用这个方法的相关信息,比如参数,方法名,返回值等等。

具体实现方式:
通过JoinPoint接口的下面几个方法获取

方法说明
getTarget()获取被代理的目标对象
getClass()获取被代理的目标对象的类
getSimpleName()获取被代理的目标对象的简单类名(不含包名)
getArgs()获取方法参数数组
getSignature()获取方法签名,包括方法名、返回类型、参数类型等信息
getModifiers()获取方法修饰符

有三个案例分别是一般情况,需要返回值情况,还有异常情况

一般情况(前置通知、后置通知)

案例代码:

需要在方法调用中参数加入JoinPoint接口实例化对象用以创建对应的动态代理,并通过动态代理获取对象相关信息。

public class advice {@Before("execution(* com.alphamilk.*.*(..))")public void Before(JoinPoint joinPoint) {
//        获取类名String simpleName = joinPoint.getTarget().getClass().getSimpleName();
//        获取方法修饰符int modifiers = joinPoint.getSignature().getModifiers();String Moidfier = Modifier.toString(modifiers);
//        获取方法名称String name = joinPoint.getSignature().getName();
//        获取参数Object[] args = joinPoint.getArgs();
//System.out.println("调用的方法是" + name);System.out.println("调用的类是" + simpleName);for (Object arg : args) {System.out.println(arg);}System.out.println("调用方法前");}@After("execution(* com.alphamilk.*.*(..))")public void After(JoinPoint joinPoint) {System.out.println("调用方法后");}
}

有返回值的情况(返回通知)

在一般情况的前提下,还需要多增加Object result参数用以接收返回值.和注解增加returning输入确切的返回对象的名称。

案例代码

public class advice {@AfterReturning(value = "execution(* com.alphamilk.*.*(..))",returning = "result")public void AfterReturning(JoinPoint joinPoint,Object result) {System.out.println("调用拥有返回值的方法");System.out.println("获取到的返回值为"+result);}
}

异常情况(异常通知)

异常通知,获取异常信息,需要在一般情况的前提下,在注解中多声明一个注解throwing,在方法参数增加一个Throwable对象,并且throwing注解对应的值就是Throwable的对象名称。

案例代码:

 @AfterThrowing(value = "execution(* com.alphamilk.*.*(..))",throwing = "throwable")public void AfterThrowing(JoinPoint joinPoint,Throwable throwable) {System.out.println("调用有异常的方法");System.out.println("异常对象为"+throwable.getClass().getName());}
@SpringJUnitConfig(value = JavaConfig.class)
public class newaopTest {@Autowiredprivate Caculate caculate;@Testpublic void Test(){caculate.div(2,0);}
}


四、 切点表达式语法

1.切点表达式作用

AOP切点表达式(Pointcut Expression)是一种用于指定切点的语言,它可以通过定义匹配规则,来选择需要被切入的目标对象。

2.切点表达式语法

  • 具体值:

    • (String, int):第一个参数是字符串,第二个参数是整数。
    • (int, String):第一个参数是整数,第二个参数是字符串。
    • ():没有参数。
  • 模糊值:

    • (..):任意参数,有或者没有。
  • 部分具体和模糊:

    • (String..):第一个参数是字符串,后面可能有其他参数。
    • (..String):最后一个参数是字符串,前面可能有其他参数。
    • (String..int):字符串开头,最后一个参数是整数,中间可能有其他参数。
    • (..int..):包含整数类型的参数,位置不限,可能有其他参数。

具体实战案例:

1.查询某包某类下,访问修饰符是公有,返回值是int的全部方法

execution public int 某包.某类.*(..)

2.查询某包下类中第一个参数是String的方法

execution * 某包.某类.*(String..)

3.查询全部包下,无参数的方法!

execution * *..*.*( )

4.查询com包下,以int参数类型结尾的方法

execution * com..*.*(..int)

5.查询指定包下,Service开头类的私有返回值int的无参数方法

execution private int 指定包.Service*.*()


五、重用(提取)切点表达式

如果在每一个方法前都加上一个固定的切点表达式,那么将会十分麻烦,所以下面介绍切点表达式的重用

1.在当前类中提取

特定注解@Pointcut

注解描述
@Pointcut声明切点表达式的方法,用于定义切点的匹配规则。

通过定义一个空方法,使用@Pointcut注解并带上特定的切点表达式

案例代码:

@Component
@Aspect
public class advice {/*定义空方法空方法上加上注解@Pointcut并带上相应的切点表达式在其他增强方法上调用方法*/@Pointcut("execution(* com.alphamilk.*.*(..))" )public void blank(){}@Before("blank()")public void Before(JoinPoint joinPoint) {System.out.println("调用方法前");}@After("blank()")public void After(JoinPoint joinPoint) {System.out.println("调用方法后");}@AfterReturning(value = "blank()",returning = "result")public void AfterReturning(JoinPoint joinPoint,Object result) {System.out.println("调用拥有返回值的方法");}@AfterThrowing(value = "blank()",throwing = "throwable")public void AfterThrowing(JoinPoint joinPoint,Throwable throwable) {System.out.println("调用有异常的方法");}
}

2.创建一个存储切点类

(推荐)通过创建一个单独的存储切点的类,更加容易进行维护表达式

  使用时候加上特定类的方法名即可

案例:

存储切点的类

@Component
public class MyPointcut {@Pointcut("execution(* com.alphamilk.Impl.*.*(..))")public void pointcut1(){}
}

对应引用类

@Component
@Aspect
public class advice {@Before("com.alphamilk.Advice.MyPointcut.pointcut1()")public void Before(JoinPoint joinPoint) {System.out.println("调用方法前");}@After("com.alphamilk.Advice.MyPointcut.pointcut1()")public void After(JoinPoint joinPoint) {System.out.println("调用方法后");}@AfterReturning(value = "com.alphamilk.Advice.MyPointcut.pointcut1()",returning = "result")public void AfterReturning(JoinPoint joinPoint,Object result) {System.out.println("调用拥有返回值的方法");}@AfterThrowing(value = "com.alphamilk.Advice.MyPointcut.pointcut1()",throwing = "throwable")public void AfterThrowing(JoinPoint joinPoint,Throwable throwable) {System.out.println("调用有异常的方法");}
}

本章总结

1.SpringAop底层技术

        了解底层代理技术有jdk 与 cglib

2.初步实现AOP编程

        掌握增强注解(@Before、@AfterReturning、@AfterThrowing、@After、@Around)

        掌握@Aspect注解的使用

3.获取切点详细信息

        掌握如何通过JoinPoint接口对象获取对应方法的类,方法名称,参数,方法修饰符

        掌握三种不同情况下获取对应信息的情况(一般情况、返回通知、异常通知)

4.切点表达式语法

        熟悉切点表达式的格式

      (execution +权限修饰 +方法返回值类型+方法所在全类名+方法名称+参数列表)

5.重用(提取)切点表达式

        

相关文章:

Spring AOP基于注解方式实现和细节

目录 一、Spring AOP底层技术 二、初步实现AOP编程 三、获取切点详细信息 四、 切点表达式语法 五、重用&#xff08;提取&#xff09;切点表达式 一、Spring AOP底层技术 SpringAop的核心在于动态代理&#xff0c;那么在SpringAop的底层的技术是依靠了什么技术呢&#x…...

CVPR2023论文及代码合集来啦~

以下内容由马拉AI整理汇总。 下载&#xff1a;点我跳转。 狂肝200小时的良心制作&#xff0c;529篇最新CVPR2023论文及其Code&#xff0c;汇总成册&#xff0c;制作成《CVPR 2023论文代码检索目录》&#xff0c;包括以下方向&#xff1a; 1、2D目标检测 2、视频目标检测 3、…...

基于ETLCloud的自定义规则调用第三方jar包实现繁体中文转为简体中文

背景 前面曾体验过通过零代码、可视化、拖拉拽的方式快速完成了从 MySQL 到 ClickHouse 的数据迁移&#xff0c;但是在实际生产环境&#xff0c;我们在迁移到目标库之前还需要做一些过滤和转换工作&#xff1b;比如&#xff0c;在诗词数据迁移后&#xff0c;发现原来 MySQL 中…...

TDesign在按钮上加入图标组件

在实际开发中 我们经常会遇到例如 添加或者查询 我们需要在按钮上加入图标的操作 TDesign自然也有预备这样的操作 首先我们打开文档看到图标 例如 我们先用某些图标 就可以点开下面的代码 可以看到 我们的图标大部分都是直接用tdesign-icons-vue 导入他的组件就可以了 而我…...

Linux 终端命令行 产品介绍

Linux命令手册内置570多个Linux 命令&#xff0c;内容包含 Linux 命令手册。 【软件功能】&#xff1a; 文件传输 bye、ftp、ftpcount、ftpshut、ftpwho、ncftp、tftp、uucico、uucp、uupick、uuto、scp备份压缩 ar、bunzip2、bzip2、bzip2recover、compress、cpio、dump、gun…...

计算机毕设 基于深度学习的植物识别算法 - cnn opencv python

文章目录 0 前言1 课题背景2 具体实现3 数据收集和处理3 MobileNetV2网络4 损失函数softmax 交叉熵4.1 softmax函数4.2 交叉熵损失函数 5 优化器SGD6 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&a…...

【STM32】学习笔记-江科大

【STM32】学习笔记-江科大 1、STM32F103C8T6的GPIO口输出 2、GPIO口输出 GPIO&#xff08;General Purpose Input Output&#xff09;通用输入输出口可配置为8种输入输出模式引脚电平&#xff1a;0V~3.3V&#xff0c;部分引脚可容忍5V输出模式下可控制端口输出高低电平&#…...

Doris架构中包含哪些技术?

Doris主要整合了Google Mesa(数据模型)&#xff0c;Apache Impala(MPP Query Engine)和Apache ORCFile (存储格式&#xff0c;编码和压缩)的技术。 为什么要将这三种技术整合? Mesa可以满足我们许多存储需求的需求&#xff0c;但是Mesa本身不提供SQL查询引擎。 Impala是一个…...

《vue3实战》通过indexOf方法实现电影评价系统的模糊查询功能

目录 前言 一、indexOf是什么&#xff1f;indexOf有什么作用&#xff1f; 含义&#xff1a; 作用&#xff1a; 二、功能实现 这段是查询过程中过滤筛选功能的代码部分: 分析&#xff1a; 这段是查询用户和性别功能的代码部分&#xff1a; 分析&#xff1a; 三、最终效…...

java对时间序列每x秒进行分组

问题&#xff1a;将一个时间序列每5秒分一组&#xff0c;返回嵌套的list&#xff1b; 原理&#xff1a;int除int会得到一个int&#xff08;也就是损失精度&#xff09; 输入&#xff1a;排序后的list&#xff0c;每几秒分组值 private static List<List<Long>> get…...

八月更新 | CI 构建计划触发机制升级、制品扫描 SBOM 分析功能上线!

点击链接了解详情 这个八月&#xff0c;腾讯云 CODING DevOps 对持续集成、制品管理、项目协同、平台权限等多个产品模块进行了升级改进&#xff0c;为用户提供更灵活便捷的使用体验。以下是 CODING 新功能速递&#xff0c;快来看看是否有您期待已久的功能特性&#xff1a; 01…...

Spring核心配置步骤-完全基于XML的配置

Spring框架的核心配置涉及多个方面&#xff0c;包括依赖注入&#xff08;DI&#xff09;、面向切面编程&#xff08;AOP&#xff09;等。以下是一般情况下配置Spring应用程序的核心步骤&#xff1a; 1. **引入Spring依赖&#xff1a;** 在项目的构建工具&#xff08;如Maven、…...

宏基官网下载的驱动怎么安装(宏基笔记本如何安装系统)

本文为大家介绍宏基官网下载的驱动怎么安装宏基笔记本驱动(宏基笔记本如何安装系统)&#xff0c;下面和小编一起看看详细内容吧。 宏碁笔记本怎么一键更新驱动 1. 单击“开始”&#xff0c;然后选择“所有程序”。 2. 单击Acer&#xff0c;然后单击Acer eRecovery Management。…...

基于AVR128单片机抢答器proteus仿真设计

一、系统方案 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 void timer0_init() //定时器初始化 { TCCR00x07; //普通模式&#xff0c;OC0不输出&#xff0c;1024分频 TCNT0f_count; //初值&#xff0c;定时为10ms TIFR0x01; //清中断标志…...

openGauss学习笔记-54 openGauss 高级特性-MOT

文章目录 openGauss学习笔记-54 openGauss 高级特性-MOT54.1 MOT特性及价值54.2 MOT关键技术54.3 MOT应用场景54.4 不支持的数据类型54.5 使用MOT54.6 将磁盘表转换为MOT openGauss学习笔记-54 openGauss 高级特性-MOT openGauss引入了MOT&#xff08;Memory-Optimized Table&…...

InsCode AI 创作助手

RESTful API是一种架构风格和设计原则&#xff0c;用于构建Web服务和应用程序。它基于HTTP协议&#xff0c;以资源为中心&#xff0c;对资源进行各种操作。RESTful API的主要特点包括&#xff1a; 使用HTTP协议进行传输和通信&#xff1b;操作和状态均以资源为中心&#xff1b…...

java对时间序列根据阈值进行连续性分片

问题描述&#xff1a;我需要对一个连续的时间戳list进行分片&#xff0c;分片规则是下一个数据比当前数据要大于某一个阈值则进行分片&#xff1b; 解决方式&#xff1a; 1、输入的有顺序的list &#xff0c;和需要进行分片的阈值 2、调用方法&#xff0c;填入该排序的list和阈…...

Pillow:Python的图像处理库(安装与使用教程)

在Python中&#xff0c;Pillow库是一个非常强大的图像处理库。它提供了广泛的图像处理功能&#xff0c;让我们可以轻松地操作图像&#xff0c;实现图像的转换、裁剪、缩放、旋转等操作。此外&#xff0c;Pillow还支持多种图像格式的读取和保存&#xff0c;包括JPEG、PNG、BMP、…...

自然语言处理-NLP

目录 自然语言处理-NLP 致命密码&#xff1a;一场关于语言的较量 自然语言处理的发展历程 兴起时期 符号主义时期 连接主义时期 深度学习时期 自然语言处理技术面临的挑战 语言学角度 同义词问题 情感倾向问题 歧义性问题 对话/篇章等长文本处理问题 探索自然语言…...

柠檬水找零【贪心算法-】

柠檬水找零 在柠檬水摊上&#xff0c;每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品&#xff0c;&#xff08;按账单 bills 支付的顺序&#xff09;一次购买一杯。 每位顾客只买一杯柠檬水&#xff0c;然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零&…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...