Spring AOP讲解

news2024/11/15 11:01:12

目录

Spring AOP概念

AOP适用场景

AOP 组成

1、切面(Aspect)

2、切点(Pointcut)

3、通知(Advice)

4、连接点(Join Point)

Spring AOP实现

添加AOP框架依赖

定义切面和切点

AspectJ表达式说明

 定义通知

SpringAOP的原理

织入(代理的生成时机)

动态代理

JDK 及 CGLIB 的方式的异同点


Spring AOP概念

AOP :面向切面编程,它是⼀种思想,它是对某⼀类事情的集中处理。

        就比如说在进行登录注册界面验证时,凡是需要使用到注册登录的方法,都需要添加登录注册验证代码。

        因此在使用AOP之后,我们只需要在某⼀处配置⼀下,所有需要判断⽤户登录⻚⾯(中的方法)就全部可以实现⽤户登录验证了,不再需要每个⽅法中都写相同的⽤户登录验证了。

Spring AOP :AOP 是一种思想,而Spring AOP是一个框架,实现了对AOP思想的实现。

AOP适用场景

        对于一些功能统一而且许多地方需要经常使用,这时候就可以使用AOP来进行统一进行处理了。

AOP的实现功能:

        1.统一的用户登录注册判断

        2.统一日志记录

        3.统一方法执行时间统计

        4.统一返回格式设置

        5.统一的异常处理

        6.事务的开启和提交等

AOP相当于是一个拦截器,需要经过AOP的验证才可访问服务器,效果图如下:

        

AOP 组成

1、切面(Aspect)

切面是包含了:通知、切点和切面的类,相当于 AOP 实现的某个功能的集合
通俗的说, 切面在程序里面就是处理一个某方面具体问题的类,类中的方法就是切点和通知

2、切点(Pointcut

用来进行主动拦截的规则(配置)

切点相当于保存了众多连接点的⼀个集合(如果把切点看成⼀个表,⽽连接点就是表中⼀条⼀条 的数据)

3、通知(Advice)

切面所需要完成的工作就是通知。

通知:定义了切⾯是什么,何时使⽤,其描述了切面要完成的⼯作,还解决何时执行这个工作的问题。
Spring 切面类中,可以在方法上使用注解,会设置方法为通知方法,在满足条件后会通知本方法进⾏调⽤。

常见的通知注解如下:

  • 前置通知: 使用 @Before,通知方法会在目标方法调用之前执行。
  • 后置通知: 使用 @After,通知方法会在目标方法返回或者抛出异常后调用。
  • 返回之后通知: 使用 @AfterReturning,通知方法会在目标方法返回后调用。
  • 抛异常后通知: 使用 @AfterThrowing,通知方法会在目标方法抛出异常后调用。
  • 环绕通知: 使用 @Around,通知包裹了被通知的方法,在被通知的方法通知之前和调用之后,执行自定义的行为。

4、连接点(Join Point

        应⽤执⾏过程中能够插⼊切⾯的⼀个点,这个点可以是⽅法调⽤时,抛出异常时,甚⾄修改字段
时。切⾯代码可以利⽤这些点插⼊到应⽤的正常流程之中,并添加新的行为
        通俗的理解为:可能会触发AOP规则的所有请求

Spring AOP实现

添加AOP框架依赖

进入中央仓库官网:​​​​​​​https://mvnrepository.com/  并在搜索框中搜索AOP 

在项目中pom.xml查看自己的Spring Boot项目版本

 

 

2.7.12版本的AOP依赖

<!-- 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.12</version>
		</dependency>

 

定义切面和切点

定义切面

@Aspect  //告诉框架是一个切面
@Component //随着框架启动而启动
public class UserAspect {

}

定义切点

 /*
    * 切点(配置拦截规则)
    * */

    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut(){

    }
  pointcut 方法为空方法,它不需要有方法体,此方法名就是起到⼀个“标识”的作⽤,标识下⾯的通知方法具体指的是哪个切点(因为切点可能有很多个)

 

AspectJ表达式说明

AspectJ ⽀持三种通配符
* :匹配任意字符,只匹配⼀个元素(包,类,或⽅法,⽅法参数)
.. :匹配任意字符,可以匹配多个元素 ,在表示类时,必须和 * 联合使⽤。
+ :表示按照类型匹配指定类的所有类,必须跟在类名后⾯,如 com.cad.Car+ ,表示继承该类的所有子类包括本身

AspectJ 表达式由切点函数组成,其中 execution() 是最常⽤的切点函数,⽤来匹配方法,语法为:
        execution(<修饰符><返回类型><包.类.方法(参数)><异常>)

注意:返回类型与包之间用一个空格隔开

示例: execution(* com.cad.demo.User.*(..)) :匹配 User 类里的所有方法
修饰符和异常可以省略,具体含义如下:

修饰符(一般省略):

public    公共方法

     *          任意

返回类型(一般不省略):

void  返回没有值

String  返回值字符串

*              任意

包:(一般情况下要有但是可以省略)

  1. com.gyf.crm      固定包
  2. com.gyf.crm.*.service      crm包下面子包任意 (例如: com.gyf.crm.staff.service)
  3. com.gyf.crm..        crm包下面的所有子包 (含自己)
  4. com.gyf.crm.*.service..         crm包下面任意子包,固定目录service,service目录任意包

类(一般情况下要有但是可以省略):

UserServicelmpl     指定类,

*Impl        以Impl结尾,

User        以User开头

   *                 任意

方法名(不可省略):

addUser        固定方法

add*        以add开头

*Do        以Do结尾

  *                任意

参数:

() 无参

(int) 一个参数

(int,int) 两个参数

(..)   任意参数

异常:throws 一般省略。

 定义通知

 

定义通知代码:

package com.example.demo.AOP;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Aspect  //告诉框架是一个切面
@Component //随着框架启动而启动
public class UserAspect {

    /*
    * 切点(配置拦截规则)
    * */

    @Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
    public void pointcut(){

    }

    /*
    * 前置通知*/
    @Before("pointcut()")
    public void beforeAdvice(){
        System.out.println("执行了前置通知~");
    }

    /*
    * 后置通知*/
    @After("pointcut()")
    public void afterAdvice(){
        System.out.println("执行了后置通知~");
    }

    /*
    * 环绕通知*/
    @Around("pointcut()")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("进入了环绕通知~");
        Object obj = null;
        obj = joinPoint.proceed();
        System.out.println("退出环绕通知~");
        return obj;
    }

}

拦截代码:

package com.example.demo.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/hello")
public class UserController {

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

运行启动类

 

 

SpringAOP的原理

          Spring AOP 是构建在动态代理基础上,因此 Spring 对 AOP 支持局限于方法级别的拦截,Spring AOP 支持 JDK Proxy 和 CGLIB 方式实现动态代理

        我们在前后端交互的时候没有代理的时候前后端是直接进行交互的,但是这样我们就需要去校验前端的一些数据等,如果我们有代理的话那么前端会先将数据传到代理代理做一个处理然后代理再将数据给后端,如此一来我们就可以专注于代码逻辑了。

织入(代理的生成时机)

        织⼊是把切⾯应⽤到⽬标对象并创建新的代理对象的过程,切⾯在指定的连接点被织⼊到⽬标对象中。

在⽬标对象的⽣命周期⾥有多个点可以进⾏织⼊:

  • 编译期:切⾯在⽬标类编译时被织⼊。这种⽅式需要特殊的编译器。AspectJ的织⼊编译器就是以这种⽅式织⼊切⾯的。
  • 类加载期:切⾯在⽬标类加载到JVM时被织⼊。这种⽅式需要特殊的类加载(ClassLoader),它可以在⽬标类被引⼊应⽤之前增强该⽬标类的字节码。AspectJ5的加载时织⼊(load-time weaving. LTW)就⽀持以这种⽅式织⼊切⾯。
  • 运⾏期:切⾯在应⽤运⾏的某⼀时刻被织⼊。⼀般情况下,在织⼊切⾯时,AOP容器会为⽬标对象动态创建⼀个代理对象。SpringAOP就是以这种⽅式织⼊切⾯的。

动态代理

        动态代理指的是在程序运行时动态地创建一个实现特定接口或一组接口的对象,该对象可以拦截并处理所有传递给它的方法调用。动态代理通常是通过在运行时生成字节码来实现的,从而避免了在编译时手工编写代理类的繁琐过程。

        我们学习 Spring 框架中的AOP,主要基于两种⽅式:JDK 及 CGLIB 的⽅式。这两种⽅式的代理⽬标都是被代理类中的⽅法,在运⾏期,动态的织⼊字节码⽣成代理类。

JDK 及 CGLIB 的方式的异同点

相同点:

  1. 它们都使用了反射机制来实现动态代理。
  2. 都可以在运行时动态生成代理对象,在代理对象中调用委托类的方法。

区别:

  1. JDK 是官方提供的,CGLIB 是第三方提供的。
  2. CGLIB 比 JDK 更高效。
  3. JDK 实现,要求被代理类必须实现接⼝,之后是通过 InvocationHandler 及 Proxy,在运⾏时动态的在内存中⽣成了代理类对象,该代理对象是通过实现同样的接⼝实现(类似静态代理接⼝实现的⽅式),只是该代理类是在运⾏期时,动态的织⼊统⼀的业务逻辑字节码来完成。CGLIB 实现,被代理类可以不实现接⼝,是通过继承被代理类,在运⾏时动态的⽣成代理类对象所以相对而言更加的灵活。
  4. CGLIB 是通过实现继承代理对象来实现动态代理的。如果代理的对象是最终类(被 final 修饰的类),Spring AOP 才会去调用 JDK 的方式生成 动态代理。

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

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

相关文章

解决 An attempt was made to call a method that does not exist. 问题详解

哈喽大家好&#xff0c;我是阿Q。今天在开发代码的过程中&#xff0c;由于手抖&#xff0c;不知道引入了什么包依赖&#xff0c;导致项目启动一直报错&#xff0c;特写本文来记录下解决问题的经过。 文章目录 问题描述报错信息如下报错描述 解决方法总结 有想赚点外块|技术交流…

hadoop基础(二)

JAVA客户端 环境搭建 创建Maven项目,添加Hadoop依赖. <dependencies><!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId…

神级插件Bito介绍及使用

还在用其他AI?不是说它不火了&#xff0c;而是你基本上很难访问了。这里介绍个便宜且免费的AI聊天插件&#xff0c;一样可以很棒。永久免费且不限制次数&#xff0c;有这好事&#xff1f;且听下文分解。 前言 虽然GPT 是用不了&#xff0c;推荐下国内的一些大模型&#xff0c…

Win10下pytorch3D安装方法,本人亲测可用

本人的电脑配置如下&#xff1a; GPU&#xff1a;GTX 1050TiCUDA&#xff1a;11.1python&#xff1a;3.8pytorch&#xff1a;1.9.0pytorch3d&#xff1a;0.7.1NVIDIA CUB&#xff1a;cub-1.9.10-1 目录 1.版本确认 2.下载cub 3.下载pytorch3d 4.下载VSC2019 5.编译pytorch…

Web3开发准备工作 手把手带你创建自己的 MetaMask 账号

查看本文 您需要在自己的谷歌浏览器中添加 扩展工具 MetaMask 如果没有添加 可以查看文章 Web3 将 MetaMask添加入谷歌浏览器 扩展程序中 我们打开它并点击开始使用 那么 我们第一次进来 肯定是啥都没有 所以 我们点 创建钱包 他这里 就会先跟你说清楚 他不会收集你的 秘钥 地…

握手信号的打拍

在数字电路的设计中,对关键路径的处理方法之一就是插入寄存器,然而,对握手信号插入寄存器则需要进行特殊的处理,否则可能导致数据传输的错乱,严重影响电路的功能。 如图所示,为了阐述对握手信号打拍的处理方式,我们给出了下图所示的简化模型,其中,上游的握手信号包括v…

OpenCV迭代去畸变undistortPoints 与vins的迭代不同 第二章vins前端 第三章imu预积分 第四章vio初始化

OpenCV去畸变undistortPoints原理解析 不动点迭代法—单变量非线性方程近似根matlab求解 淦VINS-MONO源码 03–openCV与VINS中去畸变方法的不同 这里用的方法和openCV不同&#xff0c;假设现在求A点的去畸变坐标&#xff0c;那么我们将A的坐标直接代入畸变模型中&#xff0c;求…

【Leetcode】2. 两数相加

一、题目 1、题目描述 给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。 请你将两个数相加,并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。 示例1: …

知识图谱项目——红色文化之张学良人物知识图谱(Neo4j+vue+flask+mysql实现)

张学良人物简史知识图谱_说明文档 本项目为人工智能专业大三知识图谱课程期末作业。意在完成一个以张学良为背景的红色文化类知识图谱。文末放上本项目的代码地址。 文章目录 张学良人物简史知识图谱_说明文档:rocket:前端:rocket:后端:rocket:中间件:rocket:数据库:rocket:服…

深度学习(22)——YOLO系列(2)

深度学习&#xff08;22&#xff09;——YOLO系列&#xff08;2&#xff09; 文章目录 深度学习&#xff08;22&#xff09;——YOLO系列&#xff08;2&#xff09;1. model2. dataset3. utils4. test/detect5. detect全过程 今天先写YOLO v3的代码&#xff0c;后面再出v5&…

代码托管/版本控制工具:Git的安装和使用

目录 一、Git的下载和安装二、Git基本配置三、代码上传到远程仓库四、代码下载到本地 一、Git的下载和安装 1.登录GitHub官网https://github.com/注册账户密码 2.登录https://git-scm.com/download/win &#xff08;根据自己电脑的位数和系统下载git&#xff09; 3.双击Gi…

02-IDEA 集成Maven

一. 下载IDEA编辑器 下载地址&#xff1a;Download IntelliJ IDEA – The Leading Java and Kotlin IDE 选中免费开源的社区版本 创建桌面图标和添加安装路径到系统变量&#xff0c;其他的默认安装即可。 二. 配置Maven环境 分为局部配置和全局配置 1. 局部配置maven环境 …

004依赖

传递 一个坐标引入多个jar 传递 子工程 引入了父pom 也是一种传递 继承 继承是为了消除重复&#xff0c;如果将 dao、service、web 分开创建独立的工程则每个工程的 pom.xml 文件中的内容存在重复&#xff0c;比如&#xff1a;设置编译版本、锁定 spring 的版本的等&#xff…

和鲸社区数据分析每周挑战【第九十三期:特斯拉充电桩分布分析】

和鲸社区数据分析每周挑战【第九十三期&#xff1a;特斯拉充电桩分布分析】 文章目录 和鲸社区数据分析每周挑战【第九十三期&#xff1a;特斯拉充电桩分布分析】一、前言二、数据读取和初步探索三、数据探索及可视化1、获取拥有最多充电站的 10 个国家2、一年中各月新开业数量…

I.MX RT1170之FlexSPI详解:FlexSPI基础知识和特性

最近我也在做RT1170的相关项目&#xff0c;由于项目需要&#xff0c;研究了Flash下载算法、NOR Flash空间的擦除/烧写(OTFAD XIP更新固件时要更新OTFAD Key Blob字段)、HyperRAM初始化等功能&#xff0c;这些都是开发过程中可能会遇到的一些问题&#xff0c;而这些都与FlexSPI接…

第2章 信息技术发展

文章目录 2.1.2计算机网络1.网络标准协议2.软件定义网络3.第五代移动通信技术 2.1.3存储和数据库1.存储技术2.数据结构模型3.常用数据库类型4.数据仓库 2.1.4信息安全2.1.5信息技术的发展2.2.1物联网2.2.2云计算2.2.3大数据2.2.4区块链2.2.5人工智能2.2.6虚拟现实 信息技术是在…

前端vue入门(纯代码)09

【09.vue中组件的自定义事件】 自定义组件链接 在vue中用的click【点击】、keyup【按键】……等事件&#xff0c;这些属于内置事件&#xff0c;也就是js自带的事件。 问题一&#xff1a;什么是组件自定义事件呢&#xff1f; 【内置事件】:是给html元素用的&#xff0c;比如s…

UG\NX二次开发 加密锁(加密狗)

文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan 加密锁简介 加密狗是一种用于保护软件版权的技术手段,它可以限制未经授权的用户在未经许可的情况下使用某些软件。软件加密锁可以保护软件开发商的知识产权,防止盗版和非法复制等行为,同时也可以…

React 对比class与Effect Hook优化响应式数据更新监听,感受useEffect真正的强大

还是之前写过的一个组件 import React from "react"export default class index extends React.Component{constructor(props){super(props);this.state {name: "小猫猫"}}componentDidMount ()>{document.title this.state.name;}componentDidUpda…

msvcr110.dll,丢失修复,msvcr110.dll,丢失修复详细解决办法

我们在运行软件程序或者游戏的时候&#xff0c;如果程序提示“无法启动此程序&#xff0c;因为计算机中丢失msvcr110.dll。尝试重新安装该程序以解决此问题”&#xff0c;如果说明您电脑系统中缺少或者未注册msvcr110.dll这个运行库文件&#xff0c;那么我们要如何解决这个问题…