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

Spring AOP(2)

目录

Spring AOP详解

@PointCut

切面优先级@Order

切点表达式

execution表达式

切点表达式示例

@annotation

 自定义注解@MyAspect

 切面类

添加自定义注解


Spring AOP详解

@PointCut

上面代码存在一个问题, 就是对于excution(* com.example.demo.controller.*.*(..))的大量重复使用, Spring提供了@PointCut注解, 把公共的切点表达式提取出来, 需要用到时引入切点表达式即可.

@Slf4j
@Component
@Aspect
public class AspectDemo {//声明一个切点@Pointcut("execution(* com.bite.aop.controller.*.*(..))")public void pt(){}; //切点名称:pt()@Before("pt()")public void doBefore() {//此处省略...}@After("pt()")public void doAfter() {//此处省略...}@Around("pt()")public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {//此处省略...}@AfterReturning("pt()")public void doAfterReturning() {//此处省略...}
}

 当切点定义为private修饰时, 仅能在当前切面类使用, 当其他切面类也要使用当前切点定义时, 就需要把private改为public. 引用方式为: 全限定类名.方法名()

使用示例:

@Slf4j
@Aspect
@Component
public class AspectDemo2 {//前置通知@Before("com.example.demo.aspect.AspectDemo.pt()")public void doBefore() {log.info("卢本伟牛逼");}
}

切面优先级@Order

当我们在一个项目中, 定义了多个切面类时, 并且这些切面类的多个切入点都匹配到了同一个目标方法. 当目标方法运行的时候, 这些切面类中的通知方法都会执行, 那么这些通知方法的执行顺序是怎样的呢?

还是通过程序求证:

定义多个切面类如下:

@Component
public class AspectDemo2 {@Pointcut("execution(* com.example.demo.controller.*.*(..))")private void pt(){}//前置通知@Before("pt()")public void doBefore() {log.info("执⾏ AspectDemo2 -> Before ⽅法");}//后置通知@After("pt()")public void doAfter() {log.info("执⾏ AspectDemo2 -> After ⽅法");}
}@Component
public class AspectDemo3 {@Pointcut("execution(* com.example.demo.controller.*.*(..))")private void pt(){}//前置通知@Before("pt()")public void doBefore() {log.info("执⾏ AspectDemo3 -> Before ⽅法");}//后置通知@After("pt()")public void doAfter() {log.info("执⾏ AspectDemo3 -> After ⽅法");}
}@Component
public class AspectDemo4 {@Pointcut("execution(* com.example.demo.controller.*.*(..))")private void pt(){}//前置通知@Before("pt()")public void doBefore() {log.info("执⾏ AspectDemo4 -> Before ⽅法");}//后置通知@After("pt()")public void doAfter() {log.info("执⾏ AspectDemo4 -> After ⽅法");}
}

运行指定接口,可以得到日志:

通过上述程序的运行结果, 可以看出:

存在多个切面类时, 默认按照切面类的类名字母排序:

@Before通知: 字母排名靠前的先执行;

@After通知: 字母排名靠后的后执行

 但是哥们不想这么搞, 哥们想让它们按照哥们的想法排序, 到这里我们就可以使用@Order来对切面优先级排序.

使用方式如下:

@Aspect
@Component
@Order(2)
public class AspectDemo2 {//代码省略...
}@Aspect
@Component
@Order(1)
public class AspectDemo3 {//代码省略...
}@Aspect
@Component
@Order(3)
public class AspectDemo4 {//代码省略...
}

执行结果如下:

通过上述程序的运行结果, 得出结论: 

@Order注解标识的切面类, 执行顺序如下:

@Before通知: 数字越小先执行

@After通知: 数字越大先执行

 @Order控制切面的优先级控制切面的优先级, 先执行优先级较高的切面, 在执行优先级较低的切面, 最终执行目标方法.

切点表达式

上面的代码中, 我们一直在使用切点表达式来描述切点,  下面我们来介绍一下切点表达式的语法.

切点表达式常见有两种表达方式

1.execution(......): 根据方法的签名来匹配

2.annotation(......): 根据注解来匹配. 

execution表达式

execution()作为常用的表达式, 语法为:

execution(<访问修饰符> <返回类型> <包名.类名.方法(方法参数)> <异常>) 

其中: 访问修饰符和异常可以省略

切点表达式支持通配符表达:

1. * : 匹配任意字符, 只匹配任意一个元素(返回类型, 包, 类名, 方法名, 方法参数) 

2. .. :匹配多个连续的任意符号, 可以通配任意层级的包, 或任意类型, 任意个数的参数 

切点表达式示例

TestController下的public 修饰, 返回类型为String方法名为t1, 无参方法

execution(public String com.example.demo.controller.TestController.t1())

省略访问修饰符:

​execution(String com.example.demo.controller.TestController.t1())

匹配所有类型:

execution(* com.example.demo.controller.TestController.t1())

匹配TestController下的所有无参方法:

execution(* com.example.demo.controller.TestController.*())

匹配TestController下的所有方法

​execution(* com.example.demo.controller.TestController.*(..))

匹配controller包下所有类的所有方法:

​​execution(* com.example.demo.controller.*.*(..))

匹配所有包下的TestController

​execution(* com..TestController.*(..))

@annotation

execution表达式更适用于有规则的, 如果我们要匹配出多个无规则的方法呢? 比如: 匹配TestController中的t1(), 和UserController中的u1()这两个方法.

这个时候使用execution就不是很方便了, 因此这里引入@annotation来表示这一类的切点

实现步骤:

1.编写自定义注解

2.使用@annotation表达式来描述切点

3.在连接点的方法上添加自定义注解.

准备测试代码:

@Slf4j
@RequestMapping("/test")
@RestController
public class TestController {@MyAspect@RequestMapping("/t1")public String t1() {log.info("执行t1方法...");return "t1";}@RequestMapping("/t2")public boolean t2() {log.info("执行t2方法");return true;}
}@Slf4j
@RequestMapping("/user")
@RestController
public class UserController {@RequestMapping("/u1")public String u1() {log.info("执行u1方法...");return "u1";}@MyAspect@RequestMapping("/u2")public boolean u2() {log.info("执行u2方法");return true;}
}
 自定义注解@MyAspect

创建一个注解类:

定义如下代码:

//注解类型
@Target({ElementType.METHOD})
//注解生命周期
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAspect {}

这里只做简单说明, 不必深究:

1.@Target标识了Annotation所修饰对象的范围, 即该注解用于什么地方(上文就是用于方法)

2.@Retention指Annotation被保留的时间长短, 标明注解的生命周期. 

 切面类

使用@annotation切点表达式定义切点, 只对@MyAspect生效.

切面类代码如下:

@Slf4j
@Component
@Aspect
public class MyAspectDemo {//前置通知@Before("@annotation(com.example.demo.aspect.MyAspect)")public void before() {log.info("MyAspect -> before ...");}//后置通知@After("@annotation(com.example.demo.aspect.MyAspect)")public void after() {log.info("MyAspect -> after ...");}    
}
添加自定义注解

在TestController中的t1()和 UserController中的u1()这两个方法上添加自定义注解 @MyAspect.

    @MyAspect@RequestMapping("/t1")public String t1() {log.info("执行t1方法...");return "t1";}@MyAspect@RequestMapping("/u2")public boolean u2() {log.info("执行u2方法");return true;}

顺利执行.

Spring AOP实现方式(常见面试题)

1.基于注解@Aspect

2.基于自定义注解

3.基于Spring API(现在很少见)

4.基于代理实现(笨重, 不建议使用).

相关文章:

Spring AOP(2)

目录 Spring AOP详解 PointCut 切面优先级Order 切点表达式 execution表达式 切点表达式示例 annotation 自定义注解MyAspect 切面类 添加自定义注解 Spring AOP详解 PointCut 上面代码存在一个问题, 就是对于excution(* com.example.demo.controller.*.*(..))的大量重…...

Spring-依赖注入的处理过程

前置知识 1 入口 DefaultListableBeanFactory#resolveDependency 2 每个依赖都有对应的DependencyDescriptor 3 自定绑定候选对象处理器AutowireCapableBeanFactory 注入处理 我们可以看到接口AutowireCapableBeanFactory中有两个方法。 第一个是单个注入&#xff1a; Null…...

2.用python爬取的保存在text文件中的格式为MP4的视频url

文章目录 一、url的保存格式二、MP4视频获取 一、url的保存格式 爬取的视频名字和url保存在text文件中&#xff0c;每一个视频都是一个单独的text&#xff0c;其中text的文件名就是视频的名字&#xff0c;text内容是视频的下载url&#xff0c;并且所有的text都保存在同一个文件…...

Java基于B/S医院绩效考核管理平台系统源码java+springboot+MySQL医院智慧绩效管理系统源码

Java基于B/S医院绩效考核管理平台系统源码javaspringbootMySQL医院智慧绩效管理系统源码 医院绩效考核系统是一个关键的管理工具&#xff0c;旨在评估和优化医院内部各部门、科室和员工的绩效。一个有效的绩效考核系统不仅能帮助医院实现其战略目标&#xff0c;还能提升医疗服…...

UE 蓝图堆栈调试

蓝图打断点后如果想查看断点前的执行逻辑&#xff0c;Tools→Debug→BlueprintDebugger 然后打断点运行&#xff0c;执行顺序是从下往上...

UE4_摄像机_使用摄像机的技巧

学习笔记&#xff0c;不喜勿喷&#xff01;祝愿生活越来越好&#xff01; 知识点&#xff1a; a.相机跟随。 b.相机抖动。 c.摄像机移动 d.四元数插值&#xff08;保证正确旋转方向&#xff09;。 e.相机注视跟踪。 1、新建关卡序列&#xff0c;并给小车添加动画。 2、创…...

ssm115乐购游戏商城系统+vue

毕业生学历证明系统 设计与实现 内容摘要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统毕业生学历信息管理难…...

【可实战】被测需求理解(需求文档是啥样的、从哪些角度进行需求评审、需求分析需要分析出哪些内容、如何提高需求分析能力)

产品人员会产出一个需求文档&#xff0c;然后组织一个需求的宣讲。测试人员的任务就是在需求宣讲当中&#xff0c;分析需求有没有存在一些问题&#xff0c;然后在需求宣讲结束之后通过分析需求文档&#xff0c;分析里面的测试点并预估一个排期。 一、需求文档是什么样的&#x…...

伪类和伪元素的区别是什么?

一、两者的定义 1.伪类&#xff08;pseudo-class&#xff09;是一个以冒号作为前缀&#xff0c;被添加到一个选择器末尾的关键字&#xff0c;当你希望样式在特定状态才被呈现到指定的元素时&#xff0c;你可以往元素的选择器后面加上对应的伪类。 2.伪元素用于创建一些不在文档…...

gorm-sharding分表插件升级版

代码地址&#xff1a; GitHub - 137/gorm-sharding: Sharding 是一个高性能的 Gorm 分表中间件。它基于 Conn 层做 SQL 拦截、AST 解析、分表路由、自增主键填充&#xff0c;带来的额外开销极小。对开发者友好、透明&#xff0c;使用上与普通 SQL、Gorm 查询无差别.解决了原生s…...

MoviePy(Python音视频开发)

音视频基础帧率、码率、分辨率视频格式H.264和H.265视频压缩算法 Moviepy常见剪辑类VideoFlieClipImageFlieClipColorClipTextClipCompositeVideoClipAudioFlieClipCompositeAudioClip 常见操作音视频的读入与导出截取音视频 音视频基础 帧率、码率、分辨率 体积&#xff08;V…...

Spring中的FileCopyUtils:文件复制的利器与详解

1. 概述 在Spring框架中&#xff0c;FileCopyUtils是一个用于文件复制操作的实用工具类。它提供了一系列静态方法&#xff0c;简化了文件从输入流到输出流、从文件到文件等的复制过程。这些方法都基于NIO&#xff08;New I/O&#xff09;技术&#xff0c;提供了高效的文件复制…...

【操作系统】读者—写者问题python解析

一个数据问价或记录可以被多个进程共享&#xff0c;我们把只读该文件的进程称为“读者进程”&#xff0c;其他进程为“写者进程”。允许多个进程同时读一个共享对象&#xff0c;但不允许一个写者进程和其他写者进程或读者进程同时访问共享对象。即&#xff1a;保证一个写者进程…...

【driver5】调用堆栈函数,printk,动态打印,ftrace,proc,sysfs

文章目录 1.内核函数调用堆栈&#xff1a;4个函数2.printk&#xff1a;cat /proc/cmdline查看consolettyS03.动态打印&#xff1a;printk是全局的且只能设打印等级&#xff0c;动态打印可控制选择模块的打印&#xff0c;在内核配置打开CONFIG_DYNAMIC_DEBUG4.top&perf&…...

计算机毕业设计springboot基于vue电商抢购限时秒杀系统ch0h8

技术栈 ide工具&#xff1a;IDEA 或者eclipse 编程语言: java 数据库: mysql5.7以上版本 可选框架&#xff1a;ssmspringboot都有的 前端&#xff1a;vue.jsElementUI 详细技术&#xff1a;springbootSSMvueMYSQLMAVEN 数据库工具&#xff1a;Navicat/SQLyog都可以 开发工具 Ec…...

顺序表的实现(迈入数据结构的大门)(2)

目录 顺序表的头插(SLPushFront) 此时&#xff1a;我们有两个思路&#xff08;数组移位&#xff09; 顺序表的头删(学会思维的变换)(SLPopFront) 顺序表的尾插(SLPushBack) 有尾插就有尾删 既然头与尾部的插入与删除都有&#xff0c;那必然少不了指定位置的插入删除 查找…...

学习笔记:IEEE 1003.13-2003【POSIX PSE51接口列表】

一、POSIX PSE51接口列表 根据IEEE 1003.13-2003&#xff0c;整理了POSIX PSE51接口API&#xff08;一共286个&#xff09;&#xff0c;每个API支持链接查看。详细内容参考下面表格&#xff1a; SN Module/_POSIX_宏 Function File 1 POSIX_C_LANG_JUMP(2) longjmp() &…...

《QT实用小工具·五十》动态增删数据与平滑缩放移动的折线图

1、概述 源码放在文章末尾 该项目实现了带动画、带交互的折线图&#xff0c;包含如下特点&#xff1a; 动态增删数值 自适应显示坐标轴数值 鼠标悬浮显示十字对准线 鼠标靠近点自动贴附 支持直线与平滑曲线效果 自定义点的显示类型与大小 自适应点的数值显示位置 根据指定锚点…...

【qt】核心机制信号槽(下)

这里写目录标题 自定义的信号自定义的槽自定义的信号和槽的结合使用信号和槽的断开总结&#xff1a; 自定义的信号 信号就是一个函数声明 前面咱们都用的qt组件自带的信号&#xff0c;接下来我们自己写一个信号。 信号只需要在前面加一个signals即可 这个函数不需要实现 参数传…...

C++ 基础 输入输出

一 C 的基本IO 系统中的预定义流对象cin和cout: 输入流&#xff1a;cin处理标准输入&#xff0c;即键盘输入&#xff1b; 输出流&#xff1a;cout处理标准输出&#xff0c;即屏幕输出&#xff1b; 流&#xff1a;从某种IO设备上读入或写出的字符系列 使用cin、cout这两个流对…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

省略号和可变参数模板

本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...