【springBoot】springAOP

AOP的概述

AOP是面向切面编程。切面就是指某一类特定的问题,所以AOP也可以理解为面向特定方法编程。AOP是一种思想,拦截器,统一数据返回和统一异常处理是AOP思想的一种实现。简单来说:AOP是一种思想,对某一类事务的集中处理。

spring对AOP进行了实现,并且提供了一些API,这就是spring AOP.

spring AOP的简单使用

预先准备:

@RestController
public class TestController {@RequestMapping("/t1")public String t1(){String sum = "";for (int i = 1; i <= 10000; i++) {sum += 'a';}return "t1";}@RequestMapping("/t2")public String t2(){StringBuilder sum = new StringBuilder();for (int i = 1; i <= 10000; i++) {sum.append('a');}return "t2";}
}
  1. 引入springAOP依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  1. 编写AOP程序
@Slf4j
@Aspect//表示是一个切面类
@Component
public class TimeAspect {@Around("execution(* com.example.aopdemo.controller.*.*(..))")//作用域public Object timeCost(ProceedingJoinPoint joinPoint) throws Throwable {long start = System.currentTimeMillis();//方法执行前的逻辑Object result = joinPoint.proceed();//执行目标方法long end = System.currentTimeMillis();//方法执行后的逻辑log.info(joinPoint + "消耗时间:" + (end - start) + "ms");return result;}
}

我们通过AOP⼊⻔程序完成了业务接⼝执⾏耗时的统计.

@Around:环绕通知,在⽬标⽅法的前后都会被执⾏.后⾯的表达式表⽰对哪些⽅法进⾏增强

优点:

  • 代码⽆侵⼊:不修改原始的业务⽅法,就可以对原始的业务⽅法进⾏了功能的增强或者是功能的改变
  • 减少了重复代码
  • 提⾼开发效率
  • 维护⽅便

spring AOP 详解

spring AOP 的核心概念(了解)

  1. 切点:一组规则,通过表达式来描述
  2. 连接点: 切面要作用的方法,目标方法切点描述的方法.
  3. 通知:具体的逻辑,要做什么事情
  4. 切面:切点+通知

image-20240201200843227

com.example.aopdemo.controller目录下的方法就是连接点。

切点和连接点的关系:连接点是满⾜切点表达式的元素.切点可以看做是保存了众多连接点的⼀个集合.

spring AOP通知类型

  • @Around:环绕通知,此注解标注的通知方法在目标方法前,后都被执行 --> 使用最多
  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行
  • @After:后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行
  • @AfterReturning:返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行
  • @AfterThrowing:异常后通知,此注解标注的通知方法发⽣异常后执行
@Slf4j
@Aspect
@Component
public class AspectDemo {//定义切点@Pointcut("execution(* com.example.aopdemo.controller.*.*(..))")public void pt(){}@Before("pt()")//后置通知public void doBefore(){log.info("执行AspectDemo doBefore……");}@After("pt()")//前置通知public void doAfter(){log.info("执行AspectDemo doAfter……");}@AfterReturning("pt()")//返回后通知public void doAfterReturning(){log.info("执行AspectDemo doAfterReturning……");}@AfterThrowing("pt()")//异常后通知public void doAfterThrowing(){log.info("执行AspectDemo doAfterThrowing……");}@SneakyThrows@Around("pt()")//环绕通知public Object doAround(ProceedingJoinPoint joinPoint){log.info("执行AspectDemo doAround前……");Object result = joinPoint.proceed();log.info("执行AspectDemo doAround后……");return result;}
}

正常执行结果:

先执行around,再执行before。先执行after,再执行Around。

image-20240201204352259

异常执行结果:

当发生异常时,不执行AfterReturning,也不执行Around的方法后的逻辑

image-20240201204522479

@PointCut,定义切点

如果其他类需要使用,需要把切点声明为public.使用时,类的全限定名称+切点名称 ==> 包+类名

@Slf4j
@Aspect
@Component
public class AspectDemo1 {@After("com.example.aopdemo.aspect.AspectDemo.pt()")//前置通知public void doAfter(){log.info("执行AspectDemo1 doAfter……");}
}

切面的优先级

定义三个切面类:

@Slf4j
@Aspect
@Component
public class AspectDemo1 {@Before("com.example.aopdemo.aspect.AspectDemo.pt()")//后置通知public void doBefore(){log.info("执行AspectDemo1 doBefore……");}@After("com.example.aopdemo.aspect.AspectDemo.pt()")//前置通知public void doAfter(){log.info("执行AspectDemo1 doAfter……");}
}
@Slf4j
@Aspect
@Component
public class AspectDemo2 {@Before("com.example.aopdemo.aspect.AspectDemo.pt()")//后置通知public void doBefore(){log.info("执行AspectDemo2 doBefore……");}@After("com.example.aopdemo.aspect.AspectDemo.pt()")//前置通知public void doAfter(){log.info("执行AspectDemo2 doAfter……");}
}
@Slf4j
@Aspect
@Component
public class AspectDemo3 {@Before("com.example.aopdemo.aspect.AspectDemo.pt()")//后置通知public void doBefore(){log.info("执行AspectDemo3 doBefore……");}@After("com.example.aopdemo.aspect.AspectDemo.pt()")//前置通知public void doAfter(){log.info("执行AspectDemo3 doAfter……");}
}

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

  • @Before通知:字母排名靠前的先执行
  • @After通知:字母排名靠前的后执行

image-20240201211100129

优先级高:先执行before,后执行After

Spring给我们提供了一个新的注解,来控制这些切面通知的执行顺序:@Order。使用@Order时,数字越小,优先级越高

@Order(2)
public class AspectDemo1 {
}
@Order(3)
public class AspectDemo2 {
}
@Order(1)
public class AspectDemo3 {
}

执行结果:

image-20240201211631225

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

image-20240201211754075

切点表达式

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

  1. execution(…):根据方法的签名来匹配
  2. @annotation(…):根据注解匹配

execution表达式上面已经用过.

主要介绍切点表达式支持通配符表达:

    • :匹配任意字符,只匹配一个元素(返回类型,包,类名,方法或者方法去参数
    • 包名使用 * 表示任意包(一层包使用一个*)
    • 类名使用 * 表示任意类
    • 返回值使用 *表示任意返回值类型
    • 方法名使用 * 表示任意方法
    • 参数使用 * 表示一个任意类型的参数
  1. … :匹配多个连续的任意符号,可以通配任意层级的包,或任意类型,任意个数的参数

    • 使用 … 配置包名,标识此包以及此包下的所有子包
    • 可以使用 … 配置参数,任意个任意类型的参数

execution表达式更适用有规则的,如果我们要匹配多个无规则的方法,比如:TestController中的t1和UserController中的u1()这两个方法。这个时候我们使用execution这种切点表达式来描述就不是是很方便了。我们可以借助自定义注解的方式以及另一种切点表达式@annotation来描述这一类的切点。

实现步骤:

  1. 编写自定义注解
  2. 使用@annotation表达式来描述切点
  3. 在连接点的方法上添加自定义注解

准备测试代码:

@RestController
public class UserController {@RequestMapping("/hello")public String hello(){return "hello";}@RequestMapping("/h1")public String h1(){return "h1";}@RequestMapping("/h2")public String h2(){return "h2";}
}

编写自定义注解:

@Target({ElementType.METHOD})//标识了 Annotation所修饰的对象范围,即该注解可以用在什么地方(方法上)
@Retention(RetentionPolicy.RUNTIME)//指Annotation被保留的时间长短,标明注解的生命周期(运行时注解)
public @interface MyAspect {
}

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

@Slf4j
@Component
@Aspect
public class MyAspectDemo {@Before("@annotation(com.example.aopdemo.aspect.MyAspect)")public void doBefore(){log.info("执行MyAspectDemo before...");}@After("@annotation(com.example.aopdemo.aspect.MyAspect)")public void doAfter1(){log.info("执行MyAspectDemo doAfter...");}//所有使用RequestMapping注解都会触发@After("@annotation(org.springframework.web.bind.annotation.RequestMapping)")public void doAfter(){log.info("执行RequestMapping doAfter...");}
}

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

@MyAspect    
@RequestMapping("/h1")
public String h1(){return "h1";
}

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

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

相关文章

Camtasia2024官方标准版重磅发布更新及新版本功能介绍

Camtasia 2024标准版是一款功能强大的屏幕录制和视频编辑软件。它继承了Camtasia系列一贯的易用性和丰富功能&#xff0c;为用户提供了高效、专业的视频制作体验。 在屏幕录制方面&#xff0c;Camtasia 2024标准版支持录制电脑屏幕上的任何内容&#xff0c;包括网站、软件、视…

9、内网安全-横向移动Exchange服务有账户CVE漏洞无账户口令爆破

用途&#xff1a;个人学习笔记&#xff0c;有所借鉴&#xff0c;欢迎指正&#xff01; 背景&#xff1a; 在内网环境的主机中&#xff0c;大部分部署有Exchange邮件服务&#xff0c;对于Exchange服务的漏洞也是频出&#xff0c;在这种情况下&#xff0c;如果拿到内网中一台主机…

harbor(docker仓库)仓库部署 - 高可用

harbor&#xff08;docker仓库&#xff09;仓库部署 - 高可用 1. harbor高可用1.1 方案说明1. 双主复制2. 多harbor实例共享后端存储 1.2 部署高可用&#xff08;多harbor实例共享后端存储&#xff09;1. 服务器划分2. 安装harbor&#xff08;先部署一套Harbor&#xff0c;用于…

PostgreSQL与MySQL,谁更胜一筹

前言 PostgreSQL与MySQL都是优秀的开源数据库。在日常学习中&#xff0c;新手可能接触最多的是MySql,但是实际工作中&#xff0c;两者的应用场景其实都很广。我之前的做过上网流量销售业务&#xff0c;用的是MySQL,现在接触广告业务&#xff0c;用的是pg数据库&#xff0c;每天…

深入理解 v-for 中 key 的重要性

查看本专栏目录 关于作者 还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#x…

【k8s核心概念与专业术语】

k8s架构 1、服务的分类 服务分类按如下图根据数据服务支撑&#xff0c;分为无状态和有状态 无状态引用如下所示&#xff0c;如果一个nginx服务&#xff0c;删除后重新部署有可以访问&#xff0c;这个属于无状态&#xff0c;不涉及到数据存储。 有状态服务&#xff0c;如redis&a…

RF 框架实现企业级 UI 自动化测试

RobotFramework 框架可以作为公司要做自动化 但是又不会代码的一种临时和紧急情况的替代方案&#xff0c;上手简单。 前言 现在大家去找工作&#xff0c;反馈回来的基本上自动化测试都是刚需&#xff01;没有自动化测试技能&#xff0c;纯手工测试基本没有什么市场。 但是很多…

探究全链路压力测试的含义与重要性

全链路压力测试是指对整个应用系统的各个环节或组件进行压力测试&#xff0c;以模拟实际生产环境中的用户负载和流量&#xff0c;评估系统在高负载条件下的性能表现。 1. 全链路压力测试的含义 全链路压力测试涉及系统的所有组件和环节&#xff0c;包括前端用户界面、应用服务器…

初始Nginx(基本概念)

目录 一、Nginx的概念 二、Nginx常用功能 1、HTTP(正向)代理&#xff0c;反向代理 1.1正向代理 1.2 反向代理 2、负载均衡 2.1 轮询法&#xff08;默认方法&#xff09; 2.2 weight权重模式&#xff08;加权轮询&#xff09; 2.3 ip_hash 3、web缓存 三、基础特性 四…

(3)llvm ir转换过程

&#xff08;1&#xff09;DAG Lowering 输入的IR转换成SelectionDAG的过程被称作lowering 就是把llvm ir转成这种 &#xff08;2&#xff09;DAG legalization "DAG legalization"&#xff08;有向无环图合法化&#xff09;是编译器后端&#xff0c;特别是在LLVM中…

WebStorm 2023:让您更接近理想的开发环境 mac/win版

JetBrains WebStorm 2023激活版下载是一款强大而智能的Web开发工具&#xff0c;专为提高开发人员的生产力而设计。这款编辑器提供了许多先进的代码编辑功能&#xff0c;以及一系列实用的工具和插件&#xff0c;可帮助您更快地编写、调试和测试代码。 WebStorm 2023软件获取 We…

不可不知的Redis秘籍:事务命令全攻略!

在数据处理的世界里&#xff0c;事务&#xff08;Transaction&#xff09;是一个不可或缺的概念。它们确保了在一系列操作中&#xff0c;要么所有的操作都成功执行&#xff0c;要么都不执行。这就像是一个“全有或全无”的规则&#xff0c;保证了数据的一致性和完整性。 今天&…

【算法与数据结构】127、LeetCode单词接龙

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;示例1为例&#xff0c;hit到达cog的路线不止一条&#xff0c;如何找到最短是关键。广度优先搜索是一圈…

vscode突然连不上服务器了,以前都可以的,并且ssh等其它方式是可以连接到服务器的

过完年回来准备开工干活&#xff0c;突然发现vscode连不上服务器了&#xff0c;奇了怪了&#xff0c;年前都可以的&#xff0c;看了一下报错&#xff0c;如下&#xff0c; 以为是服务器挂了&#xff0c;结果执行ssh xxxxxx 发现是可以远程连接的&#xff0c;看来服务器没有问题…

【算法与数据结构】841、LeetCode钥匙和房间

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;之前的岛屿问题可以看做是无向图&#xff0c;因为所有连接陆地都是互通的。而本题是一个有向图&#x…

搜维尔科技:【周刊】适用于虚拟现实VR中的OptiTrack

适用于 VR 的 OptiTrack 我们通过优化对虚拟现实跟踪最重要的性能指标&#xff0c;打造世界上最准确、最易于使用的广域 VR 跟踪器。其结果是为任何头戴式显示器 (HMD) 或洞穴自动沉浸式环境提供超低延迟、极其流畅的跟踪。 OptiTrack 主动式 OptiTrack 世界领先的跟踪精度和…

crmeb多门店商城系统二次开发 增加车辆车牌搜索功能、车辆公里数

1、增加的数据库 ALTER TABLE eb_store_order ADD cart_number VARCHAR(255) NOT NULL DEFAULT COMMENT 车牌 AFTER erp_order_id, ADD curmileage VARCHAR(255) NOT NULL DEFAULT COMMENT 当前里程 AFTER cart_number; ALTER TABLE eb_store_cart ADD cart_number VARCHAR(…

SOLIDWORKS Visualize 界面介绍

现在有越来越多的朋友在工作中选择使用SOLIDWORKS Visualize正版软件&#xff0c;这真是太棒了!这次的主题是小索带大家了解SOLIDWORKS Visualize界面&#xff0c;让更多的朋友快速的熟悉SOLIDWORKS Visualize界面。 【菜单栏】位于界面的顶端&#xff0c;菜单栏包含多个下拉菜…

MATLAB环境下基于短时傅里叶变换和Rényi熵的脑电信号和语音信号分析

傅里叶变换是不能很好的反映信号在时域的某一个局部范围的频谱特点的&#xff0c;这一点很可惜。因为在许多实际工程中&#xff0c;人们对信号在局部区域的特征是比较关心的&#xff0c;这些特征包含着十分有用的信息。这类信号因为在时域(或者是空间域)上具有突变的非稳定性和…

线程池的基础使用和执行策略

什么是线程池 线程池&#xff0c;字面意思就是一个创建线程的池子&#xff0c;它的特点就是&#xff0c;在使用线程之前&#xff0c;就一次性把多个线程创建好&#xff0c;放到"池”当中。后面需要执行任务的时候&#xff0c;直接从"线程池"当中通过线程执行。…