JavaEE高阶---Spring AOP

news/2024/12/5 4:45:13/

一:什么是Spring AOP?

首先,AOP是一种思想,它是对某一类事情的集中处理。 如用户登录权限的效验,没学 AOP 之前,我们所有需要判断用户登录的页面,都要各自实现或调用验证的方法。然后有了 AOP 之后,我们只需要在某一处配置一下,所有需要,判断用户登录的页面就全部可以实现用户登录验证了,不再需要在每个方法中都写相同的用户登录验证了。

AOP是一种思想,而Spring AOP是这种思想的一种具体实现。
在这里插入图片描述

二:AOP的作用

在这里插入图片描述

三:如何学习Spring AOP?

Spring AOP 学习主要分为以下 3 个部分:

  1. 学习 AOP 是如何组成的?也就是学习 AOP 组成的相关概念。
  2. 学习 Spring AOP 使⽤。
  3. 学习 Spring AOP 实现原理。

四:AOP的组成

在这里插入图片描述

AOP整个组成部分的概念示意图,以多个页面都要访问用户登录权限为例:

在这里插入图片描述

五:Spring AOP的使用

概述:
a).添加Spring AOP 框架支持;
b).定义切面和切点;
c).定义通知。

1.添加Spring AOP 框架支持。

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

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

2.定义切面和切点。

package com.example.demo.aop;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;/*** 登录的AOP实现代码*/@Component
@Aspect // 标识当前类为一个切面
public class LoginAOP {// 定义切点@Pointcut("execution(* com.example.demo.controller.UserController.*(..))")public void pointcut() {}
}

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

在这里插入图片描述

3.定义通知。


package com.example.demo.aop;import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;/*** 登录的AOP实现代码*/@Component
@Aspect // 标识当前类为一个切面
public class LoginAOP {// 定义切点@Pointcut("execution(* com.example.demo.controller.UserController.*(..))")public void pointcut() {}// 前置通知@Before("pointcut()")public void doBefore() {System.out.println("执行了前置通知");}// 后置通知@After("pointcut()")public void doAfter() {// 后置通知实现的具体业务代码System.out.println("执行了后置通知");}// return 之前通知@AfterReturning("pointcut()")public void doAfterReturning(){System.out.println("执行了返回之前通知");}// 抛出异常之前通知@AfterThrowing("pointcut()")public void doAfterThrowing(){System.out.println("执行了抛出异常之前通知");}
}

测试:

在这里插入图片描述
在这里插入图片描述

查看打印信息:

在这里插入图片描述

以上就是最基础的Spring AOP的实现。

与以上四种通知类型不同的是环绕通知。

package com.example.demo.aop;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;/*** 登录的AOP实现代码*/@Component
@Aspect // 标识当前类为一个切面
public class LoginAOP {// 定义切点@Pointcut("execution(* com.example.demo.controller.UserController.*(..))")public void pointcut() {}// 前置通知@Before("pointcut()")public void doBefore() {System.out.println("执行了前置通知");}// 后置通知@After("pointcut()")public void doAfter() {// 后置通知实现的具体业务代码System.out.println("执行了后置通知");}// return 之前通知@AfterReturning("pointcut()")public void doAfterReturning(){System.out.println("执行了返回之前通知");}// 抛出异常之前通知@AfterThrowing("pointcut()")public void doAfterThrowing(){System.out.println("执行了抛出异常之前通知");}// 环绕通知@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;}}

在这里插入图片描述
在这里插入图片描述

我们发现,环绕通知是最先开始最后结束的。

解释:

在这里插入图片描述

六:Spring AOP实现原理

Spring AOP 是构建在动态代理基础上,因此 Spring 对 AOP 的⽀持局限于⽅法级别的拦截。

Spring AOP ⽀持 JDK Proxy 和 CGLIB ⽅式实现动态代理。默认情况下,实现了接⼝的类,使⽤ AOP 会基于 JDK ⽣成代理类,没有实现接⼝的类,会基于 CGLIB ⽣成代理类。

在这里插入图片描述

织入(Weaving):代理的生成时机。

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

在这里插入图片描述
动态代理:

此种实现在设计模式上称为动态代理模式,在实现的技术⼿段上,都是在 class 代码运行期,动态的织⼊字节码。

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

Q : JDK和CGLIB实现的区别?

A:

  1. JDK 实现,要求被代理类必须实现接⼝,之后是通过 InvocationHandler 及 Proxy,在运⾏时动态的在内存中⽣成了代理类对象,该代理对象是通过实现同样的接⼝实现(类似静态代理接⼝实现的⽅式),只是该代理类是在运⾏期时,动态的织⼊统⼀的业务逻辑字节码来完成。
  2. CGLIB 实现,被代理类可以不实现接⼝,是通过继承被代理类,在运⾏时动态的⽣成代理类对象。

七:总结

关于Spring AOP,我们了解了:

AOP 是对某方面能力的统⼀实现,它是⼀种实现思想,Spring AOP 是对 AOP 的具体实现,Spring AOP 可通过 AspectJ(注解)的⽅式来实现 AOP 的功能,Spring AOP 的实现步骤是:

  1. 添加 AOP 框架⽀持。
  2. 定义切面和切点。
  3. 定义通知。

Spring AOP 是通过动态代理的方式,在运行期间将 AOP 代码织⼊到程序中的,它的实现⽅式有两种:JDK Proxy 和 CGLIB。


http://www.ppmy.cn/news/9698.html

相关文章

【LeetCode面试TOP100】力扣打卡第一天!

✨哈喽&#xff0c;进来的小伙伴们&#xff0c;你们好耶&#xff01;✨ &#x1f6f0;️&#x1f6f0;️系列专栏:【LeetCode面试TOP100】 ✈️✈️本篇内容:力扣Top100——第1,2题&#xff01; &#x1f680;&#x1f680;代码存放仓库gitee&#xff1a;力扣面试Top100题&…

12.动态内存

文章目录动态内存12.1动态内存和智能指针12.1.1shared_ptr类make_shared函数shared_ptr的拷贝和赋值shared_ptr自动销毁所管理的对象shared_ptr还自动释放相关联的内存使用了动态生存期的资源的类12.1.2直接管理内存使用new动态分配和初始化对象动态分配的const对象内存耗尽指针…

java基础 定时器

方式一&#xff1a;Timer TimerTask类实际上是实现了Runnable。 Timer定时器的特点和存在的问题&#xff1a; 1、Timer是单线程&#xff0c;处理多个任务按照顺序执行&#xff0c;存在延时与设置定时器的时间有出入。 2、由于单线程特性&#xff0c;一旦其中的某个任务抛出异…

(02)Cartographer源码无死角解析-(46) 2D栅格地图→CastRay()函数与贝汉明(Bresenham)算法

讲解关于slam一系列文章汇总链接:史上最全slam从零开始&#xff0c;针对于本栏目讲解(02)Cartographer源码无死角解析-链接如下: (02)Cartographer源码无死角解析- (00)目录_最新无死角讲解&#xff1a;https://blog.csdn.net/weixin_43013761/article/details/127350885 文末…

分享136个PHP源码,总有一款适合您

PHP源码 分享136个PHP源码&#xff0c;总有一款适合您 136个PHP源码下载链接&#xff1a;https://pan.baidu.com/s/1A5sR357dh_SlS7pu33lW1Q?pwdkzgn 提取码&#xff1a;kzgn import os# 查找指定文件夹下所有相同名称的文件 def search_file(dirPath, fileName):dirs os…

hevc/h264 预测编码的原理

预测编码预测编码是视频编码中的核心技术之一&#xff0c;对于视频信号来说&#xff0c;一副图像内临近的像素之间有着比较强的相关性&#xff0c;相邻图像之间也有很强的时间相关性。因此&#xff0c;先进的视频编码往往采用帧内预测和帧间预测的方式&#xff0c;使用图像内已…

[Linux_]make/Makefile

[Linux_]make/Makefile 心有所向&#xff0c;日复一日&#xff0c;必有精进专栏&#xff1a;《Linux_》作者&#xff1a;沂沐沐目录 [Linux]make/Makefile 前言 一、Mikefile 二、如何写Mikefile文件 三、原理 四、项目清理 报错&#xff1a;missing separator 前言 一个工…

Springboot Controller接口默认自动填充 业务实体参数值

前言 今天看有小伙伴求救&#xff1a; 我还是一贯如此&#xff0c; 有人不明白&#xff0c;没玩过HandlerMethodArgumentResolver 。 那么很可能不止他一个人&#xff0c; 那么我就有必要出手。 不多说&#xff0c;开搞。 正文 快速模拟出这个使用场景 &#xff1a; 假如有好多…