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

Spring AOP实现切入增强的两种方式(execution+annotation)-Demo

pom文件依赖

<!-- AOP切面编程启动环境依赖组 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

1、通过execution表达式实现切入增强

package com.xch.aop_execution.advicetype;import org.springframework.stereotype.Component;/*** 计算业务实现类** @author XuChenghe* @date 2023/8/19 17:43*/
@Component
public class Count {/*** 正常计算方法** @param num1* @param num2* @return*/public Integer normal(Integer num1, Integer num2) {System.out.println("-----执行正常计算方法的逻辑(开始)-----");int x = 1 / 1;System.out.println("-----执行正常计算方法的逻辑(结束)-----");return num1 + num2;}/*** 异常计算方法** @param num1* @param num2* @return*/public Integer abnormal(Integer num1, Integer num2) {System.out.println("-----执行异常计算方法的逻辑(开始)-----");int x = 1 / 0;System.out.println("-----执行异常计算方法的逻辑(结束)-----");return num1 - num2;}}
package com.xch.aop_execution.advicetype;import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;import java.util.Arrays;/*** 计算业务的切面类:测试通知类型* -其中,后置通知/返回通知 和 最终通知的执行顺序,会根据Spring的版本而异** @author XuChenghe* @date 2023/8/19 17:41*/
@Aspect // 声明该类的作用:切面类
@Component // 等价于@Configuration:交由Spring的IOC容器管理
public class CountAspect {/*** 定义公共切入点* execution表达式配置规则:* -execution([修饰符] 返回类型 方法全限定名称(参数) [异常])* -其中修饰符和异常可选* -参数..代表任意入参* -*代表任意返回类型或任意方法名* -*xxx/xxx*代表以xxx结尾或开头的任意方法名* -xxx.*代表xxx类下的所有方法或xxx包下所有类的所有方法* -xxx..*代表xxx包下所有包或类的所有方法*/@Pointcut("execution(* com.xch.aop_execution.advicetype.Count.*(..))")public void myPointcut() {// 公共切入点}/*** 前置通知** @param joinPoint 连接点:当前切入方法的信息*/@Before("myPointcut()")public void before(JoinPoint joinPoint) {System.out.println("=====前置通知(开始):执行安全检查逻辑=====");// 前置通知,可以拿到方法名称+方法入参String name = joinPoint.getSignature().getName();Object[] args = joinPoint.getArgs();System.out.println("name = " + name);System.out.println("args = " + Arrays.toString(args));System.out.println("=====前置通知(结束):执行安全检查逻辑=====");}/*** 后置通知/返回通知* 只有目标方法中没有抛出异常,即正常执行返回结果后,才进入该通知** @param joinPoint 连接点:当前切入方法的信息* @param result    方法执行的返回结果*/@AfterReturning(pointcut = "myPointcut()", returning = "result")public void afterReturning(JoinPoint joinPoint, Object result) {System.out.println("=====后置通知/返回通知(开始):记录日志=====");// 后置通知/返回通知,可以拿到方法名称+方法入参+方法返回值String name = joinPoint.getSignature().getName();Object[] args = joinPoint.getArgs();System.out.println("name = " + name);System.out.println("args = " + Arrays.toString(args));System.out.println("result = " + result);System.out.println("=====后置通知/返回通知(结束):记录日志=====");}/*** 最终通知* 不管目标方法中有没有抛出异常,都会进入该通知** @param joinPoint 连接点:当前切入方法的信息*/@After("myPointcut()")public void after(JoinPoint joinPoint) {System.out.println("=====最终通知(开始):释放资源=====");// 最终通知,可以拿到方法名称+方法入参String name = joinPoint.getSignature().getName();Object[] args = joinPoint.getArgs();System.out.println("name = " + name);System.out.println("args = " + Arrays.toString(args));System.out.println("=====最终通知(结束):释放资源=====");}/*** 环绕通知* 该通知等价于其余四种通知的大集合* 执行了被切入的方法代码,改变了原执行路径,需返回执行结果** @param pjp 连接点:当前切入方法的信息* @return 方法执行的返回结果* @throws Throwable 方法执行时抛出的异常*/@Around("myPointcut()")public Object around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("=====环绕通知(开始):手动开启事务=====");// 环绕通知,可以拿到方法名称+方法入参+方法返回值String name = pjp.getSignature().getName();Object[] args = pjp.getArgs();Object proceed = pjp.proceed();System.out.println("name = " + name);System.out.println("args = " + Arrays.toString(args));System.out.println("proceed = " + proceed);System.out.println("=====环绕通知(结束):手动提交事务=====");return proceed;}/*** 抛出异常后通知* 不能在Around环绕通知中捕获异常,否则不会给Spring AOP处理进入该通知** @param joinPoint 连接点:当前切入方法的信息* @param exception 方法执行时抛出的异常*/@AfterThrowing(pointcut = "myPointcut()", throwing = "exception")public void afterThrowing(JoinPoint joinPoint, Exception exception) {System.out.println("=====抛出异常后通知(开始):手动回滚事务=====");// 抛出异常后通知,可以拿到方法名称+方法入参+抛出的异常String name = joinPoint.getSignature().getName();Object[] args = joinPoint.getArgs();System.out.println("name = " + name);System.out.println("args = " + Arrays.toString(args));exception.printStackTrace();System.out.println("=====抛出异常后通知(结束):手动回滚事务=====");}}
package com.xch.aop_execution.advicetype;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;/*** 计算业务测试类** @author XuChenghe* @date 2023/8/19 18:17*/
@SpringBootTest
public class CountTest {@Autowiredprivate Count count;@Testpublic void test() {count.normal(3, 8);System.out.println();count.abnormal(8, 3);}}

2、通过annotation注解实现切入增强

package com.xch.aop_annotation.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 用户信息实体类** @author XuChenghe* @date 2023/8/19 12:37*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {/*** 用户ID*/private Integer id;/*** 用户名称*/private String name;}
package com.xch.aop_annotation.controller;import com.xch.aop_annotation.annotation.LogAnnotation;
import com.xch.aop_annotation.entity.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Arrays;
import java.util.List;/*** 用户信息管理接口层实现类** @author XuChenghe* @date 2023/8/19 12:35*/
@RestController
@RequestMapping("/user")
public class UserController {/*** 获取所有用户信息** @return*/@GetMapping("/getUserList")public List<User> getUserList() {// 模拟业务的数据库操作return Arrays.asList(new User(1, "Alice"),new User(2, "Bob"),new User(3, "Lucy"));}/*** 通过用户ID获取用户信息** @param id* @return*/@GetMapping("/getUserById/{id}")public User getUserById(@PathVariable("id") Integer id) {// 模拟业务的数据库操作return new User(1, "Alice");}/*** 通过用户名称获取用户信息** @param name* @return*/@GetMapping("/getUserByName/{name}")public User getUserByName(@PathVariable("name") String name) {// 模拟业务的数据库操作return new User(2, "Bob");}/*** 保存用户信息** @return*/@GetMapping("/saveUser")@LogAnnotation("保存用户信息")public String saveUser() {// 模拟业务的数据库操作return "添加用户信息成功!";}/*** 编辑用户信息** @return*/@GetMapping("/editUser")@LogAnnotation("编辑用户信息")public String editUser() {// 模拟业务的数据库操作return "编辑用户信息成功!";}/*** 通过用户ID删除用户信息** @param id* @return*/@GetMapping("/deleteUserById/{id}")@LogAnnotation("通过用户ID删除用户信息")public String deleteUserById(@PathVariable("id") Integer id) {// 模拟业务的数据库操作return "通过用户ID删除用户信息成功!";}/*** 通过用户名称删除用户信息** @param name* @return*/@GetMapping("/deleteUserByName/{name}")@LogAnnotation("通过用户名称删除用户信息")public String deleteUserByName(@PathVariable("name") String name) {// 模拟业务的数据库操作return "通过用户名称删除用户信息成功!";}}
package com.xch.aop_annotation.annotation;import java.lang.annotation.*;/*** 记录写操作方法日志的注解** @author XuChenghe* @date 2023/8/19 12:57*/
@Target(ElementType.METHOD) // 声明该注解作用的地方:方法
@Retention(RetentionPolicy.RUNTIME) // 声明该注解作用的时间:运行时
@Documented // 以上三个都是元注解:描述注解的注解
public @interface LogAnnotation {/*** 方法的作用描述*/String value() default "暂无作用描述(默认)";}
package com.xch.aop_annotation.aspect;import com.xch.aop_annotation.annotation.LogAnnotation;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.util.Arrays;/*** 记录写操作方法日志的的切面类** @author XuChenghe* @date 2023/8/19 13:06*/
@Aspect // 声明该类的作用:切面类
@Component // 等价于@Configuration:交由Spring的IOC容器管理
public class LogAspect {/*** 定义公共切入点*/@Pointcut("@annotation(com.xch.aop_annotation.annotation.LogAnnotation)")public void logPointCut() {// 公共切入点}/*** 切面的执行方法(环绕通知):记录日志操作的代码** @param pjp 连接点:当前切入方法的信息* @return 方法执行的返回结果*/@Around("logPointCut()")public Object around(ProceedingJoinPoint pjp) throws Throwable {// 模拟业务的记录日志到数据库操作// 当前切入的方法名称String name = pjp.getSignature().getName();// 当前切入的方法返回值(执行了被切入的方法代码,改变了原执行路径,需返回执行结果)Object proceed = pjp.proceed();// 当前切入的方法入参Object[] args = pjp.getArgs();// 获取注解的属性内容// 1.通过反射反向获取方法MethodSignature signature = (MethodSignature) pjp.getSignature();Method method = signature.getMethod();// 2.通过反射反向获取注解LogAnnotation logAnnotation = method.getAnnotation(LogAnnotation.class);if (logAnnotation != null) {String value = logAnnotation.value();System.out.println("========================================");System.out.println("name = " + name);System.out.println("proceed = " + proceed);System.out.println("args = " + Arrays.toString(args));System.out.println("value = " + value);System.out.println("========================================");}return proceed;}}

相关文章:

Spring AOP实现切入增强的两种方式(execution+annotation)-Demo

pom文件依赖 <!-- AOP切面编程启动环境依赖组 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency> 1、通过execution表达式实现切入增强 package com…...

人工智能在网络安全中的作用:当前的局限性和未来的可能性

人工智能 (AI) 激发了网络安全行业的想象力&#xff0c;有可能彻底改变安全和 IT 团队处理网络危机、漏洞和勒索软件攻击的方式。 然而&#xff0c;对人工智能的能力和局限性的现实理解至关重要&#xff0c;并且存在许多挑战阻碍人工智能对网络安全产生直接的变革性影响。 在…...

BC99 序列中整数去重

描述 输入n个整数的序列&#xff0c;要求对这个序列进行去重操作。所谓去重&#xff0c;是指对这个序列中每个重复出现的整数&#xff0c;只保留该数第一次出现的位置&#xff0c;删除其余位置。 输入描述 输入包含两行&#xff0c;第一行包含一个正整数n&#xff08;1 ≤ n…...

[PyTorch][chapter 52][迁移学习]

前言&#xff1a; 迁移学习&#xff08;Transfer Learning&#xff09;是一种机器学习方法&#xff0c;它通过将一个领域中的知识和经验迁移到另一个相关领域中&#xff0c;来加速和改进新领域的学习和解决问题的能力。 这里面主要结合前面ResNet18 例子&#xff0c;详细讲解一…...

Ceph如何操作底层对象数据

1.基本原理介绍 1.1 ceph中的对象(object) 在Ceph存储中&#xff0c;一切数据最终都会以对象(Object)的形式存储在硬盘&#xff08;OSD&#xff09;上&#xff0c;每个的Object默认大小为4M。 通过rados命令&#xff0c;可以查看一个存储池中的所有object信息&#xff0c;例如…...

sklearn机器学习库(二)sklearn中的随机森林

sklearn机器学习库(二)sklearn中的随机森林 集成算法会考虑多个评估器的建模结果&#xff0c;汇总之后得到一个综合的结果&#xff0c;以此来获取比单个模型更好的回归或分类表现。 多个模型集成成为的模型叫做集成评估器&#xff08;ensemble estimator&#xff09;&#xf…...

FlutterBoost 实现Flutter页面内嵌iOS view

在使用Flutter混合开发中会遇到一些原生比Flutter优秀的控件&#xff0c;不想使用Flutter的控件&#xff0c;想在Flutter中使用原生控件。这时就会用到 Flutter页面中内嵌 原生view&#xff0c;这里简单介绍一个 内嵌 iOS 的view。 注&#xff1a;这里使用了 FlutterBoost。网…...

走嵌入式还是纯软件?学长告诉你怎么选

最近有不少理工科的本科生问我&#xff0c;未来是走嵌入式还是纯软件好&#xff0c;究竟什么样的同学适合学习嵌入式呢&#xff1f;在这里我整合一下给他们的回答&#xff0c;根据自己的经验提供一些建议。 嵌入式领域也可以分为单片机方向、Linux方向和安卓方向。如果你的专业…...

【云计算原理及实战】初识云计算

该学习笔记取自《云计算原理及实战》一书&#xff0c;关于具体描述可以查阅原本书籍。 云计算被视为“革命性的计算模型”&#xff0c;因为它通过互联网自由流通使超级计算能力成为可能。 2006年8月&#xff0c;在圣何塞举办的SES&#xff08;捜索引擎战略&#xff09;大会上&a…...

Open3D (C++) 基于拟合高差的点云地面点提取

目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示1、原始点云2、提取结果四、相关链接系列文章(连载中。。。): Open3D (C++) 基于高程的点云地面点提取Open3D (C++) 基于拟合平面的点云地面点提取Open3D (C++) 基于拟合高差的点云地面点提取</...

认识Transformer:入门知识

视频链接&#xff1a; https://www.youtube.com/watch?vugWDIIOHtPA&listPLJV_el3uVTsOK_ZK5L0Iv_EQoL1JefRL4&index60 文章目录 Self-Attention layerMulti-head self-attentionPositional encodingSeq2Seq with AttentionTransformerUniversal Transformer Seq2Seq …...

《TCP IP网络编程》第二十四章

第 24 章 制作 HTTP 服务器端 24.1 HTTP 概要 本章将编写 HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;服务器端&#xff0c;即 Web 服务器端。 理解 Web 服务器端&#xff1a; web服务器端就是要基于 HTTP 协议&#xff0c;将网页对…...

【AI】文心一言的使用

一、获得内测资格&#xff1a; 1、点击网页链接申请&#xff1a;https://yiyan.baidu.com/ 2、点击加入体验&#xff0c;等待通过 二、获得AI伙伴内测名额 1、收到短信通知&#xff0c;点击链接 网页Link&#xff1a;https://chat.baidu.com/page/launch.html?fa&sourc…...

CSAPP Lab2:Bomb Lab

说明 6关卡&#xff0c;每个关卡需要输入相应的内容&#xff0c;通过逆向工程来获取对应关卡的通过条件 准备工作 环境 需要用到gdb调试器 apt-get install gdb系统: Ubuntu 22.04 本实验会用到的gdb调试器的指令如下 r或者 run或者run filename 运行程序,run filename就…...

Java中使用流将两个集合根据某个字段进行过滤去重?

Java中使用流将两个集合根据某个字段进行过滤去重? 在Java中&#xff0c;您可以使用流(Stream)来过滤和去重两个集合。下面是一个示例代码&#xff0c;展示如何根据对象的某个字段进行过滤和去重操作&#xff1a; import java.util.ArrayList; import java.util.List; impor…...

自动驾驶HMI产品技术方案

版本变更 序号 日期 变更内容 编制人 审核人 文档版本 1 2 1....

Git判断本地是否最新

场景需求 需要判断是否有新内容更新,确定有更新之后执行pull操作&#xff0c;然后pull成功之后再将新内容进行复制到其他地方 pgit log -1 --prettyformat:"%H" HEAD -- . "origin/HEAD" rgit rev-parse origin/HEAD if [[ $p $r ]];thenecho "Is La…...

Spring 整合RabbitMQ,笔记整理

1.创建生产者工程 spring-rabbitmq-producer 2.pom.xml添加依赖 <dependencies><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.7.RELEASE</version></dep…...

Lua 语言笔记(一)

1. 变量命名规范 弱类型语言(动态类型语言)&#xff0c;定义变量的时候&#xff0c;不需要类型修饰 而且&#xff0c;变量类型可以随时改变每行代码结束的时候&#xff0c;要不要分号都可以变量名 由数字&#xff0c;字母下划线组成&#xff0c;不能以数字开头&#xff0c;也不…...

【Redis】什么是缓存穿透,如何预防缓存穿透?

【Redis】什么是缓存穿透&#xff0c;如何预防缓存穿透&#xff1f; 缓存穿透是指查询一个一定不存在的数据&#xff0c;由于缓存中不存在&#xff0c;这时会去数据库查询查不到数据则不写入缓存&#xff0c;这将导致这个不存在的数据每次请求都要到数据库去查询&#xff0c;这…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...