【Spring Boot】Spring AOP 快速上手指南:开启面向切面编程新旅程

前言

???本期讲解关于spring aop的入门介绍~~~

??感兴趣的小伙伴看一看小编主页:-CSDN博客

?? 你的点赞就是小编不断更新的最大动力

??那么废话不多说直接开整吧~~

目录

???1.AOP概述

1.1什么是AOP

?1.2什么是Spring AOP

???2.Spring AOP入门

2.1环境设置

2.2代码编写

???3.Spring AOP详细

3.1Spring AOP核心概念

1.切点

2.连接点

3.通知

4.切面

3.2Spring AOP通知类型

3.3@pointcut注解

3.4@order切面优先级

???4.总结

**??**1.AOP概述

1.1什么是AOP

AOP是Spring框架的第核(第核是IoC),说明AOP也是非常重要的;

AOP:Aspect Oriented Programming(向切编程)

面向切面编程:所谓的这里的切面就是表示一类特殊的问题,所以也叫面向特定方法编程;

这里特定的方法,在之前学习过的spring统一功能处理中,涉及到登录校验问题,而拦截器就是对这类问题的统一求解,AOP是一种求解问题的思想,那么拦截器就是一种思想的实现;

总结:

简单来说: AOP是种思想, 是对某类事情的集中处理

1.2什么是Spring AOP

AOP是种思想, 它的实现法有很多, 有Spring AOP,也有AspectJ、CGLIB等.Spring AOP是其中的种实现式;

在日常的代码编写中,有以下列子:

假如,我们要对这里面的接口实现改良,让执行时间减少,这里就定位到某些业务代码逻辑等改进,但是不是所有都是不好的,所以我们需要进行测试每个接口,业务执行的时间,那么就有如下的代码,来进行时间检测:

此时的方法固然是可以的,但是那么多接口都需要这样写吗??答案是不可能的,此时这就是一类特定的问题,此时我们就可以使用AOP思想来进行解决~~~

AOP就可以做到在不改动这些原始法的基础上, 针对特定的法进功能的增强.
AOP的作:在程序运期间在不修改源代码的基础上对已有法进增强(侵性: 解耦)

**??**2.Spring AOP入门

2.1环境设置

首先创建一个springboot项目,设置Maven,然后引入如下的依赖

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

这里还可以引入lombok来进行slf4j日志打印,但是在新版本中要将引入的lombok中一部分给注释掉,如下所示:

           <plugins>
           <!-- <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>-->
            <plugin>
2.2代码编写

具体的代码如下所示:

@Slf4j
@Aspect
@Component
//交给spring进行管理
public class TimeAspect {

    @Around("execution(* com.example.springaop.controller.*.*(..))")
    public Object timeRecord(ProceedingJoinPoint joinPoint) throws Throwable {
        //记录开始时间
        long start = System.currentTimeMillis();
        //执行目标方法
        Object proceed = joinPoint.proceed();
        //记录结束时间
        long end = System.currentTimeMillis();
        //日志打印耗时
        log.info("耗时时间: "+ (end-start) + "ms");
        return proceed;
    }
}

解释:

1. @Aspect: 标识这是个切类
2. @Around: 环绕通知, 在标法的前后都会被执. 后的表达式表对哪些法进增强.
3. ProceedingJoinPoint.proceed() 让原始法执

那么上述代码大致分为如下:

总结优势:

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

**??**3.Spring AOP详细

3.1Spring AOP核心概念
1.切点

切点(Pointcut), 也称之为"切点"
Pointcut 的作就是提供组规则 (使 AspectJ pointcut expression language 来描述), 告诉程序对哪些法来进功能增强

如下所示:

execution(* com.example.springaop.controller.*.*(..))

这个就是切点表达式;

2.连接点

满切点表达式规则的法, 就是连接点. 也就是可以被AOP控制的法,上述切点表达式中的类就是controller,说明这里面的所有方法都是AOP控制方法;

解释:直白来说就是我们需要操作的解决的一类问题接口,就是受到AOP管理的;

这个就是连接点;

3.通知

通知就是具体要做的作, 指哪些重复的逻辑,也就是共性功能(最终体现为个法)如上述程序中记录业务法的耗时时间, 就是通知;

具体的部分就是如下:

在AOP向切编程当中, 我们把这部分重复的代码逻辑抽取出来单独定义, 这部分代码就是通知的内容.

4.切面

切(Aspect) = 切点(Pointcut) + 通知(Advice)
通过切就能够描述当前AOP程序需要针对于哪些法, 在什么时候执什么样的操作,切面包含了通知中要执行的逻辑,以及连接点的定义

3.2Spring AOP通知类型

Spring中AOP的通知类型有以下种:
@Around: 环绕通知, 此注解标注的通知法在标法前, 后都被执
@Before: 前置通知, 此注解标注的通知法在标法前被执
@After: 后置通知, 此注解标注的通知法在标法后被执, 论是否有异常都会执
@AfterReturning: 返回后通知, 此注解标注的通知法在标法后被执, 有异常不会执
@AfterThrowing: 异常后通知, 此注解标注的通知法发异常后执

那么这里主要是通过代码来进行实验;

每个通知类型的代码如下所示:

@Slf4j
@Component
@Aspect
public class AspectDemo1 {
    
    @Around("execution(* com.example.springaop.controller.*.*(..))")
    public Object aroundTest(ProceedingJoinPoint point) throws Throwable {
        //通知
        log.info("Around 开始执行");
        //执行目标函数
        Object result = point.proceed();
        //结束打印
        log.info("Around 结束执行");
        return result;
    }

    @Before("execution(* com.example.springaop.controller.*.*(..))")
    public void beforeTest(){
        log.info("before 开始执行");
    }

    @After("execution(* com.example.springaop.controller.*.*(..))")
    public void afterTest(){
        log.info("after 开始执行");
    }

    @AfterReturning("execution(* com.example.springaop.controller.*.*(..))")
    public void afterReturnTest(){
        log.info("afterReturn 开始执行");
    }

    @AfterThrowing("execution(* com.example.springaop.controller.*.*(..))")
    public void afterThrowTest(){
        log.info("afterThrow 开始执行");
    }
}

解释:

从上到下依次的通知类型,就是注解所表示,但是对于环绕通知中,要包含这里的连接点,即目标执行方法,以及返回类型是object;环绕通知需要调 ProceedingJoinPoint.proceed() 来让原始法执, 其他通知不需要考虑标法执;

此时运行如下的测试类:

@Slf4j
@RestController
@RequestMapping("/test")
public class AspectTest {
    @RequestMapping("/t1")
    public String test1(){
        log.info("这是目标方法,开始执行");
        return "t1";
    }
   @RequestMapping("/t2")
    public String test2(){
        log.info("这是目标方法,开始执行");
        int a=10/0;
        return "t2";
    }
}

那么此时我们先运行这里没有算数异常的代码,输出的情况如下所示:

解释:

程序正常运的情况下, @AfterThrowing 标识的通知法不会执
从上图也可以看出来, @Around 标识的通知法包含两部分, 个"前置逻辑", 个"后置逻辑".其
中"前置逻辑" 会先于 @Before 标识的通知法执, “后置逻辑” 会晚于 @After 标识的通知法执

此时运行异常代码,结果如下所示:

解释:

@AfterReturning 标识的通知法不会执, @AfterThrowing 标识的通知法执了
@Around 环绕通知中原始法调时有异常,通知中的环绕后的代码逻辑也不会在执了(因为
原始法调出异常了

3.3@pointcut注解

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

代码如下所示:

 @Pointcut("execution(* com.example.springaop.controller.*.*(..))")
     public void pt(){}

    @Around("pt()")
    public Object aroundTest(ProceedingJoinPoint point) throws Throwable {
        //通知
        log.info("Around 开始执行");
        //执行目标函数
        Object result = point.proceed();
        //结束打印
        log.info("Around 结束执行");
        return result;
    }

解释:

此时就是通过@pointcut注解,对于切点表达式进行了提取,那么之后再次进行通知注解的切点表达式编写时,就可以直接使用提取的方法;

这里的方法若设置为私有类,那么只能在这一个类中进行使用,但是如果其他类要使用,这里必须变成public访问限定符;

代码如下所示:

@Slf4j
@Aspect
public class AspectDemo2 {
    @Before("com.example.springaop.aspect.AspectDemo1.pt()")
    public void beforeTest() {
        log.info("AspectDemo2 before 开始执行...");
    }

其中@before注解中的切点编写就是,提取方法的全限定路径+类名+方法名;

3.4@order切面优先级

假如定义了多个切类时, 并且这些切类的多个切点都匹配到了同个标法.情况如下所示

首先定义三个切面类,里面的通知方法大致如下:

public class AspectDemo3 {
    @Before("com.example.springaop.aspect.AspectDemo1.pt()")
    public void doBefore(){
        log.info("AspectDemo3 do before...");
    }

    @After("com.example.springaop.aspect.AspectDemo1.pt()")
    public void doAfter(){
        log.info("AspectDemo3 do after...");
    }

}

此时进行路由访问后,打印的日志如下所示:

解释:

存在多个切类时, 默认按照切类的类名字排序
@Before 通知:字排名靠前的先执
@After 通知:字排名靠前的后执

那么此时我们可以通过@order注解实现顺序的逆转,代码如下所示:

@Component
@Aspect
@Order(3)
public class AspectDemo3 {
}

解释:

我们设置AspectDemo3order为3,AspectDemo4的order为2,AspectDemo5的order为1,输出的结果如下所示:

通过上述程序的运结果, 得出结论:
@Order 注解标识的切类, 执顺序如下:
@Before 通知:数字越先执
@After 通知:数字越先执
@Order 控制切的优先级, 先执优先级较的切, 再执优先级较低的切, 最终执标法

**??**4.总结

本期主要讲解了关于Spring AOP入门概念,以及快速入门,以及Spring AOP的代码的详细介绍:切点,连接点,通知,以及切面的概念,还有通知类型等其他注解的介绍~~~

???~~~~最后希望与诸君共勉,共同进步!!!


???以上就是本期内容了, 感兴趣的话,就关注小编吧。

???期待你的关注~~~

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

(01)STM32—GPIO

1. GPIO简介 GPIO&#xff08;General Purpose Input Output&#xff09;通用输入输出端口。可配置为8种输入输出模式。引脚电平&#xff1a;0V~3.3V&#xff0c;部分引脚可容忍5V。输出模式下可控制端口输出高低电平&#xff0c;用以驱动LED、控制蜂鸣器、模拟通信协议输出时…

python实现pdf转word和excel

一、引言   在办公中&#xff0c;我们经常遇收到pdf文件格式&#xff0c;因为pdf格式文件不易修改&#xff0c;当我们需要编辑这些pdf文件时&#xff0c;经常需要开通会员或收费功能才能使用编辑功能。今天&#xff0c;我要和大家分享的&#xff0c;是如何使用python编程实现…

基于 Python 的深度学习的车俩特征分析系统,附源码

博主介绍&#xff1a;✌stormjun、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&…

C#实现字符串反转的4种方法

见过不少人、经过不少事、也吃过不少苦&#xff0c;感悟世事无常、人心多变&#xff0c;靠着回忆将往事串珠成链&#xff0c;聊聊感情、谈谈发展&#xff0c;我慢慢写、你一点一点看...... 1、string.Reverse 方法 string content "Hello World";string reverseStri…

LabVIEW串口通信调试与数据接收问题

在使用LabVIEW进行串口通信时&#xff0c;常常会遇到无法接收数据的情况。这可能与串口设置、连接、设备响应等多方面因素相关。本文将详细讨论如何使用LabVIEW进行串口通信&#xff0c;并提供常见问题的排查与解决方法&#xff0c;帮助用户更高效地进行数据接收调试。通过调整…

单元测试与unittest框架

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;薪资嘎嘎涨 单元测试的定义 1. 什么是单元测试&#xff1f; 单元测试是指&#xff0c;对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作&am…

LuaJIT Garbage Collector Algorithms

Explain 本篇文章是对Make Pall发表wili内容《LuaJIT 3.0 new Garbage Collector》的翻译和扩展&#xff0c;因为原文是对LuaJIT 2.x GC重要功能的简介和对LuaJIT 3.0 new GC的工作计划&#xff0c;所以它并不是系统性介绍GC的文章。希望以后能有精力系统性的对LuaJIT 2.x GC做…

1.17组会汇报

STRUC-BENCH: Are Large Language Models Good at Generating Complex Structured Tabular Data? STRUC-BENCH&#xff1a;大型语言模型擅长生成复杂的结构化表格数据吗&#xff1f;23年arXiv.org 1概括 这篇论文旨在评估大型语言模型&#xff08;LLMs&#xff09;在生成结构…

EF Core全局查询筛选器

目录 概述 用法 添加全局查询筛选器 禁用全局查询筛选器 概述 全局查询筛选器&#xff1a;EF Core 会自动将这个查询筛选器应用于涉及这个实体类型的所有 LINQ 查询。 场景&#xff1a;软删除、多租户。 什么是软删除&#xff1f; 逻辑删除&#xff0c;并不是真正地从数…

俄语画外音的特点

随着全球媒体消费的增加&#xff0c;语音服务呈指数级增长。作为视听翻译和本地化的一个关键方面&#xff0c;画外音在确保来自不同语言和文化背景的观众能够以一种真实和可访问的方式参与内容方面发挥着重要作用。说到俄语&#xff0c;画外音有其独特的特点、挑战和复杂性&…

怎么用CRM系统实现客户数据的集中管理?

一、为什么我们需要关注客户数据&#xff1f; 嘿&#xff0c;大家好&#xff01;你有没有过这样的经历&#xff0c;在与一家公司打交道时&#xff0c;突然发现对方对你的需求了如指掌&#xff0c;并且总能提供恰到好处的服务&#xff1f;这可不是巧合哦&#xff0c;背后很可能…

学习threejs,使用OrbitControls相机控制器

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.OrbitControls 相机控…

Vue2+OpenLayers实现点位拖拽功能(提供Gitee源码)

目录 一、案例截图 二、安装OpenLayers库 三、代码实现 3.1、初始化变量 3.2、创建一个点 3.3、将点添加到地图上 3.4、实现点位拖拽 3.5、完整代码 四、Gitee源码 一、案例截图 可以随意拖拽点位到你想要的位置 二、安装OpenLayers库 npm install ol 三、代码实现…

【Spring】获取Cookie和Session(@CookieValue()和@SessionAttribute())

文章目录 获取 Cookie 传统获取 Cookie简洁获取 Cookie&#xff08;注解&#xff09; 获取 Session Session 存储和获取简洁获取 Session (1)简洁获取 Session (2) 获取 Cookie 传统获取 Cookie 这是没有 Spring 的时候&#xff0c;用 Servlet 来获取&#xff08;获取所有的…

Linux第二课:LinuxC高级 学习记录day03

4、解压和压缩 1、gzip 和 gunzip 特点&#xff1a; 1&#xff09;只能对单个普通文件进行压缩或解压 2&#xff09;不能进行归档&#xff0c;压缩后或解压缩后源文件不存在 3&#xff09;压缩生成压缩格式为.gz 命令&#xff1a; 压缩&#xff1a;gzip 文件名.c // …

OpenCV实现多尺度细节提升算法

1、算法原理 多尺度细节提升算法来源于论文*《DARK IMAGE ENHANCEMENT BASED ON PAIRWISE TARGET CONTRAST AND MULTI-SCALE DETAIL BOOSTING》*&#xff0c;算法主要是解决细节增强算法中噪声和细节的平衡问题。 常规的非锐化掩蔽&#xff08;USM&#xff09;算法在提升细节…

查看APK的公钥,MD5信息

查看md5 sha1 sha256的等信息 keytool -list -printcert -jarfile apk的路径地址 查看公钥私钥信息 keytool -list -rfc --keystore keystore文件的路径地址 | openssl x509 -inform pem -pubkey 把里面的keystore文件的路径地址替换成你的本地文件就可以了 如果报以上错误 就…

【机器学习实战入门】使用Python进行手写数字识别

什么是手写数字识别&#xff1f; 手写数字识别是计算机识别手写数字的能力。这对手工制造的设备来说是一个难题&#xff0c;因为手写数字并不完美&#xff0c;且人们书写数字的方式多种多样。手写数字识别旨在解决这一问题&#xff0c;通过使用数字的图像来识别该图像中的数字…

技术晋升读书笔记—华为研发

读完《华为研发》第三版&#xff0c;我深感震撼&#xff0c;书中的内容不仅详实地记录了华为公司的成长历程&#xff0c;还揭示了华为成功背后的管理理念和创新思路。这本书通过真实的案例和数据&#xff0c;展示了华为如何从一个小企业发展成全球通信行业的领导者。 一、关键人…

SQL server数据库导出excel操作

1、选择需要查询的数据库&#xff1a;鼠标右键—>任务—>导出数据 2、 选择数据源和服务器&#xff0c;使用sql server身份验证 &#xff08;数据源就是指需要从哪里导出到excel表格&#xff0c;这里就选择你需要导出的数据库&#xff09; 3、下一步选择要导出的excel表…