解锁Spring AOP的神秘面纱

目录

  • Spring AOP的组成
    • 组成部分与常用注解
    • 举例理解
  • Spring AOP的实现
    • 添加 Spring AOP 框架⽀持
    • 定义切⾯和切点
    • 定义通知
    • 切点表达式说明
  • Spring AOP 实现原理
    • JDK动态代理
    • CGLIB动态代理

Spring AOP作为Spring框架的核心模块,为我们提供了一种优雅的方式来处理横切关注点。本篇博客将从组成、实现和实现原理三个方面深入剖析Spring AOP,并结合具体的例子进行说明。

Spring AOP的组成

组成部分与常用注解

  • 切面(Aspect):切面是横切关注点的具体实现,它定义了在何处、何时执行横切逻辑。我们可以通过切点和通知来定义一个切面。
  • 连接点(Join Point):连接点是方法在程序执行过程中能够被拦截的特定点(这个点可以是⽅法调⽤时,抛出异常时,甚⾄修改字段
    时)。在Spring AOP中,连接点通常表示方法的执行。
  • 切点(Pointcut):切点指定了在哪些方法上应该应用切面逻辑。可以使用表达式或注解等方式来定义切点,精确定位到目标方法。
  • 通知(Advice):通知定义了在切点上执行的横切逻辑,可以在方法执行前、后或抛出异常时被触发。

在Spring 切⾯类中,可以在⽅法上使⽤以下注解,会设置⽅法为通知⽅法,在满⾜条件后会通知本⽅法进⾏调⽤:

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

举例理解

下面通过一个生活中的例子,我们可以更直观地理解Spring AOP的组成部分及其运作方式。
在这个例子中,我们可以将Spring AOP的组成部分与咖啡馆的场景联系起来:

  1. 切面(Aspect):切面就好像是咖啡馆提供的不同附加服务,比如打包、送货等。每种附加服务都是一个切面,它定义了一个特定的横切逻辑。

  2. 切点(Pointcut):切点就像是决定在哪些情况下应该提供附加服务。例如,每次有人点了咖啡,那就是一个切点,表示一个可以应用附加服务的地方。

  3. 通知(Advice):通知就是具体的附加服务的实现。在咖啡馆中,这可以是将咖啡打包的过程,或者是送货员将咖啡送到指定地点的过程。

  4. 连接点(Join Point):连接点就像是咖啡的准备过程,比如磨咖啡豆、冲泡咖啡等。这些过程都是咖啡制作的特定点,也就是连接点。

当你在咖啡馆点一杯咖啡时,Spring AOP的运作方式如下:

  1. 切面定义了附加服务,比如打包和送货。

  2. 切点决定了在哪些情况下应该提供附加服务,比如在每次点咖啡时。

  3. 通知实现了附加服务的具体逻辑,比如将咖啡打包或送到指定地点。

  4. 连接点是咖啡的制作过程,每个步骤都是一个连接点,而在某些连接点上(即切点匹配的地方),会触发附加服务的通知。

这样,当你点了一杯咖啡时,Spring AOP就会在制作咖啡的过程中,根据切点的匹配情况触发相应的附加服务通知,比如将咖啡打包好或送到指定地点。

Spring AOP的实现

Spring AOP的实现主要依赖于JDK动态代理和CGLIB动态代理两种方式。默认情况下,Spring AOP使用JDK动态代理,但也可以通过配置切换到CGLIB动态代理。

添加 Spring AOP 框架⽀持

在 pom.xml 中添加如下配置:

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

定义切⾯和切点

切点指的是具体要处理的某⼀类问题,Spring AOP 切点的定义如下,在切点中我们要定义拦截的规则,具体实现如下:

@Aspect    //表明这个类为一个切面
@Component
public class UserAspect {
  //定义切点,使⽤ AspectJ 表达式语法
    @Pointcut("execution(* com.example.springaop.Controller.UserController.* (..))")
    public void pointcut(){ }  
}

@Pointcut 注解标注的方法是一个空方法,它不需要具体的方法体。它的作用是为下面的通知方法提供一个标识,用来指定具体指向哪个切点。

定义通知

通知定义的是被拦截的⽅法具体要执⾏的业务,比如统一异常处理等待。

依旧是在刚才的切面类UserAspect中书写代码:

 // 前置通知
  @Before("pointcut()")
  public void doBefore(){
    System.out.println("执⾏ Before ⽅法");
  }

我们在UserController中写一个测试方法:

@RestController
@ResponseBody
@RequestMapping("/con")
public class UserController {
    @RequestMapping("/tsst")
    public Object test() {
        System.out.println("测试方法执行");
        return "测试";
    }
}

我们在浏览器进行访问测试方法:
在这里插入图片描述
在这里插入图片描述
通过控制台信息发现前置通知方法的实现在测试方法之前,至于其他通知方法我们也补全于切面类当中

    // 后置通知
    @After("pointcut()")
    public void doAfter() {
        System.out.println("执⾏ After ⽅法");
    }

    @AfterReturning("pointcut()")
    public void doAfterReturning() {
        System.out.println("执⾏ return 之前通知⽅法");
    }

    @AfterThrowing
    public void doAfterThrowing() {
        System.out.println("执行异常抛出之前的通知方法");
    }

    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) {
        Object obj = new Object();

        System.out.println("开始执行环绕通知方法");
        try {
            //执行目标方法
            joinPoint.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        System.out.println("环绕通知方法结束");
        return obj;
    }

可以将环绕通知方法理解为包裹目标方法的一层“包装”,它可以在目标方法执行前后进行一些额外的操作和控制。通过环绕通知,我们可以在不改变目标方法原有逻辑的同时,添加一些横切关注点的功能,例如日志记录、性能监控、事务管理等。

切点表达式说明

AspectJ ⽀持三种通配符

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

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

示例:

execution(* com.cad.demo.User+.*(..))

匹配该类的⼦类包括该类的所有⽅法。

execution(* addUser(String, int))

匹配 addUser ⽅法,且第⼀个参数类型是 String,第⼆个参数类型是 int。

Spring AOP 实现原理

Spring AOP的实现原理主要依赖于动态代理机制。当使用Spring AOP时,它会在运行时为目标对象生成一个代理对象,并将切面逻辑织入到目标对象的方法调用中。
Spring AOP所使用的代理方式可以分为两种:JDK动态代理和CGLIB动态代理。

JDK动态代理

当目标对象实现了至少一个接口时,Spring AOP会使用JDK动态代理来生成代理对象。JDK动态代理是通过java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口实现的。

  • 在Spring AOP中,首先会根据目标对象和切面对象,创建一个实现了InvocationHandler接口的代理对象。
  • 当目标对象的方法被调用时,代理对象的invoke()方法会被调用。在invoke()方法内部,可以通过反射机制来执行目标方法,同时在目标方法的执行前后,插入切面逻辑。

CGLIB动态代理

当目标对象没有实现任何接口时,Spring AOP会使用CGLIB动态代理来生成代理对象。CGLIB动态代理是通过继承目标类并重写目标方法的方式实现的。

  • 在Spring AOP中,首先会针对目标对象生成一个继承了目标类的代理类,并在代理类中重写目标方法。
  • 当目标对象的方法被调用时,代理对象的相应重写方法会被调用。在重写方法中,可以在目标方法的执行前后,插入切面逻辑。

总结起来,Spring AOP的实现原理是通过动态代理机制,在运行时为目标对象生成代理对象,并将切面逻辑织入到目标对象的方法中。具体使用JDK动态代理还是CGLIB动态代理取决于目标对象是否实现了接口。

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

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

相关文章

硬编码基础一(经典定长指令,寄存器相关)

硬编码基础一&#xff08;定长指令&#xff09; push/pop 通用寄存器 50~57是push8个32位通用寄存器 58~5f是pop8个32位通用寄存器 inc/dec 通用寄存器 40~47是inc8个32位通用寄存器 47~4f是dec8个32位通用寄存器 八位通用寄存器的立即数赋值 b0~b3 {立即数} 是低八位(…

【福建事业单位-综合基础知识】05民法典

这里写自定义目录标题 一、民法概述概念原则总结 二、自然人概念总结 三、民事法律行为总结 民法考察2-4题&#xff08;重点总则篇&#xff09; 一、民法概述 概念原则 总结 二、自然人 概念 总结 三、民事法律行为 总结

C++进阶 特殊类的设计

本篇博客介绍&#xff1a;介绍几种特殊的类 特殊类的设计 设计一个类不能被拷贝设计一个类 只能在堆上创建对象设计一个类 只能在栈上创造对象设计一个类不能被继承单例模式饿汉模式懒汉模式单例模式对象的释放问题 总结 设计一个类不能被拷贝 我们的拷贝只会发生在两个场景当…

Flink状态和状态管理

1.什么是状态 官方定义&#xff1a;当前计算流程需要依赖到之前计算的结果&#xff0c;那么之前计算的结果就是状态。 这句话还是挺好理解的&#xff0c;状态不只存在于Flink&#xff0c;也存在生活的方方面面&#xff0c;比如看到一个认识的人&#xff0c;如何识别认识呢&am…

CSS中的calc()函数有什么作用?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ CSS中的calc()函数及其作用⭐ 作用⭐ 示例1. 动态计算宽度&#xff1a;2. 响应式布局&#xff1a;3. 自适应字体大小&#xff1a;4. 计算间距&#xff1a; ⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点…

Spring之bean的生命周期

目录 1.Bean的初始化过程 1.1代码详解 1.2思考 2.Bean的单例与多例选择 2.1论证单例与多例优缺点 2.2论证初始化时间点 2.3个例演示 Spring Bean的生命周期&#xff1a; 一、通过XML、Java annotation&#xff08;注解&#xff09;以及Java Configuration(配置类),等方式…

【令牌桶算法与漏桶算法】

&#x1f4a7; 令牌桶算法与漏桶算法 \color{#FF1493}{令牌桶算法与漏桶算法} 令牌桶算法与漏桶算法&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人.✨ &#x1f984; 个人主页——微风撞见云的博客&#x1f390; &#x1f433; 《数据结构与算法》专…

每日一题——螺旋矩阵

题目 给定一个m x n大小的矩阵&#xff08;m行&#xff0c;n列&#xff09;&#xff0c;按螺旋的顺序返回矩阵中的所有元素。 数据范围&#xff1a;0≤n,m≤10&#xff0c;矩阵中任意元素都满足 ∣val∣≤100 要求&#xff1a;空间复杂度 O(nm) &#xff0c;时间复杂度 O(nm)…

李沐pytorch学习-卷积网络及其实现

一、卷积概述 1.1 基本定义 卷积计算过程如图1所示&#xff0c;即输入矩阵和核函数&#xff08;filter&#xff09;对应的位置相乘&#xff0c;然后相加得到输出对应位置的数。 图1. 卷积计算过程 该过程可以形象地从图2中展现。 图2. 二维卷积示意图 1.2 实现互相关运算的代…

01-关于new Object()的问题

美团面试题关于Object o = new Object()的几个问题。 1、对象在内存中的存储布局? 实例化一个对象,在堆区开辟一段空间。 堆区由markword、类型指针(class point)、实例数据、对齐组成。 markword:由8个字节组成。 类型指针(class point):就是指向某class文件的指针,…

【3Ds Max】弯曲命令的简单使用

简介 在3ds Max中&#xff0c;"弯曲"&#xff08;Bend&#xff09;是一种用于在平面或曲面上创建弯曲效果的建模命令。使用弯曲命令&#xff0c;您可以将对象沿特定轴向弯曲&#xff0c;从而创建出各种弯曲的几何形状。以下是使用3ds Max中的弯曲命令的基本步骤&…

spring源码分析bean的生命周期(下)

doGetBean()执行过程 createBean()执行过程 一、DependsOn注解 spring创建对象之前会判断类上是否加了DependsOn注解&#xff0c;加了会遍历然后会添加到一个map中&#xff0c;spring会先创建DependsOn注解指定的类 二、spring类加载器 在合并BeanDefinition&#xff0c;确定…

solidwords(5)

我们打算从上面画出总体&#xff0c;再从上面、侧面切除 最后成品

AI重新定义音视频生产力“新范式”

// 编者按&#xff1a;AIGC无疑是当下的热门话题和场景。面对AI带来的技术变革和算力挑战&#xff0c;该如何应对&#xff1f;LiveVideoStackCon 2023上海站邀请到了网心科技副总裁武磊为我们分享网心在面对AI应用场景和业务需求下的实践经验。 文/武磊 编辑/LiveVideoStack …

2022年国考行政执法卷-判断推理

去掉重复题 例题 例题 例题 例题 例题 例题 例题 例题 例题 例题 类比推理 例题 例题 例题 例题 例题 例题

mac上如何压缩视频大小?

mac上如何压缩视频大小&#xff1f;由于视频文件体积庞大&#xff0c;常常会占据我们设备的大量存储空间。通常情况下&#xff0c;我们选择删除视频以释放内存&#xff0c;但这将永久丢失它们。然而&#xff0c;有一种更好的方法可以在不删除视频的情况下减小内存占用&#xff…

Linux网络编程:Socket套接字编程(Server服务器 Client客户端)

文章目录&#xff1a; 一&#xff1a;定义和流程分析 1.定义 2.流程分析 3.网络字节序 二&#xff1a;相关函数 IP地址转换函数inet_pton inet_ntop&#xff08;本地字节序 网络字节序&#xff09; socket函数(创建一个套接字) bind函数(给socket绑定一个服务器地址结…

计算机竞赛 图像检索算法

文章目录 1 前言2 图像检索介绍(1) 无监督图像检索(2) 有监督图像检索 3 图像检索步骤4 应用实例5 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 图像检索算法 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff…

SpringCloud Gateway:status: 503 error: Service Unavailable

使用SpringCloud Gateway路由请求时&#xff0c;出现如下错误 yml配置如下&#xff1a; 可能的一种原因是&#xff1a;yml配置了gateway.discovery.locator.enabledtrue&#xff0c;此时gateway会使用负载均衡模式路由请求&#xff0c;但是SpringCloud Alibaba删除了Ribbon的…

【es6】中的Generator

Generator 一、Generator 是什么&#xff1f;1.1 与普通函数写法不一样&#xff0c;有两个不同 二、Generator 使用2.1 书写方法 三、yield语句3.1 yield和return3.2 注意事项3.3 yield*语句3.4 yield*应用 四、next方法4.1参数 总结 一、Generator 是什么&#xff1f; Genera…