Spring AOP的概念和使用

news2024/11/28 8:43:31

什么是AOP

AOP是一种思想,它叫做面向切面编程,简单的来说就是对某一类事请做集中处理。比如说:登录效验功能,在使用AOP之前,我们进行登录效验需要在每个方法中写一遍登录效验的代码;使用AOP后,我们只需要将登录效验的代码配置起来,在需要登录效验的方法执行之前先经过登录效验的代码,这样既减少了代码量降低了代码的重复性,还让我们程序更加解耦。

什么是Spring AOP

Spring AOP是对AOP思想的一种具体实现。和IoC与DI的关系类似。

为什么要使用AOP

AOP可以实现的功能有很多:统一的事务处理、统一的日志记录、统一的异常处理、统一的返回格式设置.....

使用AOP可以给多个对象扩充某个能力,是非常实用的思想。

AOP的组成及概念

(1)切面:切面有切点和通知组成,它既包含了横切逻辑的定义,也包含了连接点的定义。

大意:切面就是一个包含了拦截逻辑(切点)和通知(拦截后要做的事)的一个类。

(2)连接点:应用执行过程中能够插入切面的一个点,这个点可以是方法调用时,抛出异常时,甚至修改字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。

大意:连接点就是可以在拦截规则之中的,可以来到切面的方法。

(3)切点:切点是匹配连接点的谓词。切点的作用就是提供一组规则来匹配连接点,给满足规则的连接点添加通知。

大意:切点是一个拦截规则,满足规则的方法就是连接点,而链接点会来到切面执行通知(执行具体内容)

(4)通知:切面的工作被称之为通知。

通知分为好几种:

前置通知:使用@Before,通知方法会在目标方法调用前执行。

后置通知:使用@After,通知方法会在目标方法返回后或抛出异常后后调用。

返回之后通知:@AfterReturn,通知方法会在目标方法返回后调用。

抛异常后通知:@AfterThrowing,通知方法会在目标方法抛出异常后调用。

环绕通知:@Around,通知将目标方法环绕,在调用目标方法的前后进行通知。

大意:切面执行的具体内容。

用程序逻辑,总结上面的概念:

切点描述的是一个范围,在范围里面的类都是符合切点的对象;

连接点就是执行到的切点,当一个在切点范围内的类,里面的方法被执行时,此时这个方法就是一个链接点;

通知就是当连接点被执行到时,在方法额外中添加的任务。举例:当通知是执行前的通知时,此时会在执行方法之前先执行通知。

切面是包含切点和通知的类。

代码实现

添加依赖到pom.xml文件中

首先打开maven商店:https://mvnrepository.com/?__cf_chl_tk=UNFVbxMbXH6Fwrcs97l6W2f8RlXbZxBy.xvqxEi3Ks0-1684329597-0-gaNycGzNDPs

然后搜索Spring AOP

找到Spring Boot Starter AOP 

找到2.x版本进行插入(2.x对应jdk8)

下面这个是2.7.11版本的maven依赖。

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.7.11</version>
</dependency>

切面类:@Aspect注解

切点:@pointcut注解

注解里面的内容如下:分为4个部分

修饰符(可省略):public、private...

返回类型:String、Integer...

范围:包、类、方法(参数)  参数部分用..表示匹配任意参数

异常(可省略):一般不写

举例:

@Aspect //切面
@Component
public class UserAOP {

    //切点(配置拦截规则)
    @Pointcut("execution(* com.example.demo.controller.UserController.login(..))")
    public void pointcut() {

    }

    //前置通知
    @Before("pointcut()")
    public void doBefore() {
        //打印当前时间
        System.out.println("执行了前置通知: " + LocalDateTime.now());
    }

    //后置通知
    @After("pointcut()")
    public void doAfter() {
        //打印当前时间
        System.out.println("执行了后置通知: " + LocalDateTime.now());
    }

    //return后通知
    @AfterReturning("pointcut()")
    public void doAfterReturning() {
        System.out.println("执行了return后通知: " + LocalDateTime.now());
    }

    //异常通知
    @AfterThrowing("pointcut()")
    public void doAfterThrowing() {
        System.out.println("执行了异常通知: " + LocalDateTime.now());
    }

    //环绕通知
    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) {
        Object obj = null;
        System.out.println("开始执行环绕通知了");
        try {
            obj = joinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("结束环绕通知了");
        return obj;
    }
}

执行类:

@Controller
@ResponseBody
public class UserController {

    @RequestMapping("/user/sayHi")
    public String sayHi() {
        System.out.println("执行了 sayHi 方法");
        return "hi, spring boot aop.";
    }

    @RequestMapping("/user/login")
    public String login() {
        System.out.println("执行了 login 方法");
        return "do user login";
    }
}

因为切点中定义只有login方法符合,此时login方法执行和sayHi方法执行如下:

login方法:

sayHi方法:

Spring AOP底层原理 

AOP的实现主要由两种:静态代理和动态代理。

静态代理可以理解为需要实现接口和类的方式实现代理,理解起来比较容易,但是写起来就比较繁琐。

动态代理是Java在运行时动态生成代理的一种方式,它使用的是Java的反射。

Spring AOP是通过动态代理来实现的。

Java实现动态代理的方式主要由两种:JDK动态代理和CGLIB动态代理。

其中JDK动态代理是使用反射的技术,它的执行速度快,但是被代理的类必须要实现接口。

CGLIB动态代理是通过实现代理类的子类来实现动态代理的,不需要实现接口,但是被final修饰的类不能被代理。

Spring AOP中既使用了JDK动态代理,又实用了CGLIB动态代理。

在默认情况下是使用JDK动态代理,但是如果被代理类没有实现接口,此时会使用CGLIB动态代理。

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

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

相关文章

chatgpt赋能Python-numpy提取数据

Numpy提取数据&#xff1a;一种高效处理数据的方法 Numpy是Python中一个用于科学计算的库&#xff0c;它提供了一些高效的数值计算工具和数据结构。其中一个重要的功能是对大量数据进行高效的处理与分析。本文将介绍Numpy提取数据的用法&#xff0c;帮助您更高效地处理数据。 …

Java参数绑定(包括按值传递和按引用传递)

在Java中&#xff0c;参数绑定是一种将实际参数值传递给方法或函数的过程。在方法调用中&#xff0c;参数绑定决定了方法的形式参数&#xff08;在方法声明中定义的参数&#xff09;和实际参数&#xff08;传递给方法的参数&#xff09;之间的关系。 Java中的参数绑定有两种形…

chatgpt赋能Python-numpy数据归一化

Numpy数据归一化&#xff1a;什么是归一化以及为什么要归一化&#xff1f; 当我们处理数据时&#xff0c;我们常常要将它们归一化。归一化是将数值范围缩放到标准范围内的过程。这可以确保不同的特征或变量在计算机算法中具有相同的权重。这对于一些机器学习算法、人工神经网络…

chatgpt赋能Python-mac_python怎么用

如何在Mac上使用Python进行编程&#xff1f; 如果你是一位Python开发者&#xff0c;想在Mac上进行编程&#xff0c;本篇文章将会告诉你如何使用Python在Mac上进行编程。首先&#xff0c;你需要确认你的Mac上是否安装了Python&#xff0c;如果你是新手&#xff0c;可以去Python…

nginx(七十六)nginx与HTTP请求行的深入探讨

一 nginx与请求行相关 nginx处理来自客户端的HTTP请求行和请求头 ① 关于请求行的变量 $request $request_method SP $request_uri SP $server_protocol "案例讲解" ② nginx作为服务端接收关于method控制 1) 请求方法和支持的协议版本包含如下: -->协议…

离线安装apisix

公司部分机器因为某些原因无法联网&#xff0c;只能离线安装apisix&#xff0c;折腾了很久&#xff0c;走了很多弯路&#xff0c;记录一下安装过程。 下载所有的包 安装epel源 sudo yum install epel-release在home下创建文件夹/apisix-dependence 下载apache-apisix-repo以…

chatgpt赋能Python-mac上的python

在Mac上使用Python编程的好处 作为一名有10年Python编程经验的工程师&#xff0c;我必须说Mac是一个出色的编程工作台。Mac操作系统本质上就是一个整合了各种开发工具的平台&#xff0c;为Python编程提供了很好的支持。这篇文章将介绍在Mac上使用Python编程的好处。 简单易用…

VOSviewer安装、环境配置及中英文文献的分析

VOSviewer介绍&#xff1a; VOSviewer是一个用于构建和可视化文献计量网络的软件工具。例如&#xff0c;这些网络可能包括期刊、研究人员或单个出版物&#xff0c;它们可以基于引文、书目耦合、共同引用或共同作者关系构建。VOSviewer 还提供文本挖掘功能&#xff0c;可用于构…

总线(计组)

概概述 基本概念 1、总线&#xff1a;是构成计算机互联的机构&#xff0c;是多个系统功能部之间进行数据传输的公共通路 2、总线的分类&#xff1a; 内部总线、系统总线、IO总线 内部总线&#xff1a;cpu连接寄存器及各运算部件的总线 系统总线&#xff1a;cpu连接其他高速功…

Typora的自定义主题

Typora的自定义主题 修改我们的Typora主题1. 在文件夹C:\Users\Peter\AppData\Roaming\Typora\themes中&#xff0c;加入下面的css文件即可&#xff0c;命名为my.css。my.css内容 2. 选择你的主题为my3. 效果如图 注意&#xff1a;如果你的字体没有完全像我一样&#xff0c;是因…

学习RHCSA的day.03

目录 2.6 Linux系统的目录结构 2.7 目录操作命令 2.8 文件操作命令 2.6 Linux系统的目录结构 1、Linux目录结构的特点 分区加载于目录结构&#xff1a; 使用树形目录结构来组织和管理文件。整个系统只有一个位于根分区的一个根目录&#xff08;树根&#xff09;、一棵树。…

chatgpt赋能Python-mac版python教程

了解Mac版Python教程 Python编程语言越来越受欢迎&#xff0c;是由其简单易学、使用广泛的特点所得。Mac用户也喜欢使用Python进行编程&#xff0c;因为Python在macOS中得到良好的支持。在本篇文章中&#xff0c;我们将介绍一些最受欢迎的Mac版Python教程&#xff0c;并提供一…

chatgpt赋能Python-a____python

理解Python的a[:]语法 Python是一门高级编程语言&#xff0c;它被广泛应用于数据分析、机器学习、人工智能等领域。在Python编程中&#xff0c;有一个很重要的语法就是a[:]。 在本文中&#xff0c;我们将介绍这个语法的含义、作用和用法&#xff0c;并帮助读者更好地理解这个语…

动态规划算法:解决复杂问题的利器

文章目录 摘要引言动态规划的基本原理动态规划的应用场景动态规划的实际代码示例总结与展望 动态规划算法的优缺点优点&#xff1a;缺点&#xff1a; 总结&#xff1a; 摘要 动态规划&#xff08;Dynamic Programming&#xff09;是一种高效解决复杂问题的算法方法&#xff0c…

如何学习网络安全?

近半年我一直在整理网络安全相关资料&#xff0c;对于网络安全该怎么入门我谈谈我的看法&#xff0c;网络安全一直处于法律的边缘&#xff0c;学的不好或者剑走偏锋一下子人就进去了&#xff0c;所以我建议入门前先熟读《网络安全法》&#xff0c;除此之外还有《互联网安全产品…

AVL树(平衡二叉搜索树)

如果BST树插入的顺序是有序的&#xff0c;那么BST树就会退化成一个双链表结构&#xff0c;查询的速率就会很慢&#xff0c; 所以有了AVL树的意义。 AVL树的定义&#xff1a; 是具有下列性质的二叉搜索树 1、它的左子树和右子树都是AVL树 2、左子树和右子树的高度之差的绝对值…

Java --- redis7之redisson的使用

目录 一、自研分布式锁核心 二、redlock红锁算法 Distributed locks with redis 2.1、设计理念 2.2、容错公式 2.3、单机案例实现 三、redisson源码分析 四、多机案例 4.1、启动三台docker的redis7 4.2、进入redis 一、自研分布式锁核心 1、按照JUC里面java.util.conc…

linux kernel pwn

基础知识 内核概述 内核架构 通常来说我们可以把内核架构分为两种&#xff1a;宏内核和微内核&#xff0c;现在还有一种内核是混合了宏内核与微内核的特性&#xff0c;称为混合内核。 宏内核&#xff08;Monolithic kernel&#xff09;&#xff0c;也译为集成式内核、单体…

工信部认可! 开源网安“源码级软件开发安全解决方案”成功入选优秀方案

日前&#xff0c;开源网安“源码级软件开发安全解决方案”成功入选工信部网络安全产业发展中心“2022年信息技术应用创新解决方案”&#xff0c;成为经工业部认可的优秀解决方案。 据悉&#xff0c;由工业和信息化部网络安全产业发展中心&#xff08;工业和信息化部信息中心&am…

【Leetcode刷题】算法:罗马数字转整数

文章目录 一、问题二、代码理解 一、问题 二、代码理解 class Solution:def romanToInt(self, s: str) -> int:answer0length len(s)d{I:1,V:5,X:10, L:50,C:100, D:500,M:1000}for i in range(length-1):if d[s[i1]]>d[s[i]]:answeranswer-d[s[i]]else:answeranswerd[…