Spring AOP

简介: Spring AOP

🔎定义


AOP(Aspect Oriented Programming)—面向切面编程

AOP 是一种思想, 是对某一类事情的集中处理

举个栗子🌰

一个程序包含众多的方法, 每个方法都需要检测用户的登录状态

于是在每个方法中 ctrl + c / v 检测用户登录状态的代码

但这样做过于麻烦, 于是将检测用户登录状态的代码封装为一个方法, 这个操作可以被理解为是" AOP "

AOP 与 Spring AOP 之间的关系类似于 IOC 与 DI, MVC 与 Spring MVC

AOP—思想 / Spring AOP—思想的具体实现(框架)

AOP 的功能🍂

  • 统一的日志记录
  • 统一的方法执行时间统计
  • 统一的返回格式设置
  • 统一的异常处理
  • 事务的开启和提交

🔎AOP 的组成


AOP 的组成

  1. 切面(Aspect)
  2. 连接点(Join Point)
  3. 切点(Pointcut)
  4. 通知(Advice)

切面(Aspect)


定义🍂

切面由切点和通知组成, 既包含了横切逻辑的定义, 也包括了连接点的定义

翻译🍂

将切面理解为程序中用于处理某方面问题的一个类

该类包含很多的方法, 这些方法就是切点和通知

切点(Pointcut)


定义🍂

切点的作用是提供一组规则来匹配连接点, 给满足规则的连接点添加通知

翻译🍂

切点的作用是配置主动拦截的规则

通知(Advice)


定义🍂

切面的工作被称为通知

翻译🍂

触发 AOP 后具体的执行流程

通知的类型🍂

  • 前置通知, 执行目标方法之前执行的通知, 使用@Before注解
  • 后置通知, 执行目标方法之后执行的通知, 使用@After注解
  • 返回通知, 目标方法执行 return(返回数据) 时执行的通知, 使用@AfterReturning注解,
  • 异常通知, 目标方法执行时出现异常执行的通知, 使用@AfterThrowing注解
  • 环绕通知, 目标方法执行周期内(执行前, 执行中, 执行后)均可执行的通知, 使用@Around注解

连接点(Join Point)


定义🍂

应用执行过程中能够插入切面的一个点

这个点可以是方法调用时, 抛出异常时, 修改字段时…

切面代码可以利用这些点插入到应用的正常流程之中, 并添加新行为

翻译🍂

可能触发 AOP 规则的所有点(所有请求)

总结


举个栗子🌰

切面 → 检测登录状态(处理某方面问题的一个类)

切点 → 设置检测登录状态的规则(配置主动拦截规则)

通知 → 触发设置的规则时执行的操作(触发 AOP 后具体的流程)

连接点 → 哪些情况下会涉及检测登录状态(可能触发 AOP 的所有请求)

🔎Spring AOP


Spring AOP 的创建


在 Spring Boot 项目基础上引入下列依赖

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

Spring AOP 的使用


使用 Spring AOP 的步骤

  1. 引入依赖
  2. 定义切面
  3. 定义切点
  4. 定义通知

定义切面🍭

@Aspect // 表示当前类是切面
@Component
public class UserAspect {
}

定义切点🍭

注意

  1. 切点无返回值
  2. @Pointcut("execution(* com.example.demo.controller.UserController.*(..))"), 切点表达式
    表示拦截 com → example → demo → controller → UserController 类下的所有方法(参数任意)
    此处省略了修饰符
/**
* 切点(配置拦截规则)
* @author bibubibu
* @date 2023/7/5
*/
@Pointcut("execution(* com.example.demo.controller.UserController.*(..))")
public void pointCut() {
}

定义通知🍭

通知分为 5 种, 此处列举的为前置通知, 后置通知, 环绕通知

注意

  1. 前置通知与后置通知无返回值, 环绕通知返回值类型为 Object
  2. 通知中注解的内容为切点(配置的拦截规则)
/**
  * 前置通知(需要声明针对的拦截规则 -> 切点)
  * @author bibubibu
  * @date 2023/7/5
  */
 @Before("pointCut()")
 public void beforeAdvice() {
     System.out.println("执行了前置通知");
 }
 /**
  * 后置通知(需要声明针对的拦截规则 -> 切点)
  * @author bibubibu
  * @date 2023/7/5
  */
 @After("pointCut()")
 public void afterAdvice() {
     System.out.println("执行了后置通知");
 }
 /**
  * 环绕通知(需要声明针对的拦截规则 -> 切点)
  * @author bibubibu
  * @date 2023/7/5
  */
 @Around("pointCut()")
 public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
     System.out.println("进入环绕通知");
     Object obj = null;
     // 执行目标方法
     obj = joinPoint.proceed();
     System.out.println("退出环绕通知");
     return obj;
 }

定义 UserController 类与 ArticleController 类🍭

  • 拦截器配置的规则是拦截 UserController 类下的所有方法, 因此对于 ArticleController 类不会生效
  • 定义 UserController 类, 查看配置拦截规则的效果
  • 定义 ArticleController 类, 对比未配置拦截规则的效果

UserController 类🍂

@RestController
@RequestMapping("/user")
public class UserController {
    @RequestMapping("/process-u")
    public String processU() {
        System.out.println("执行了 processU()");
        return "hello, UserController";
    }
}

ArticleController 类🍂

@RestController
@RequestMapping("/article")
public class ArticleController {
    @RequestMapping("/process-a")
    public String processA() {
        System.out.println("执行了 processA()");
        return "hello, ArticleController";
    }

执行前置通知 + 后置通知🍭

执行环绕通知 + 前置通知 + 后置通知🍭

切点表达式


此处使用 Aspect J 语法

Aspect J 支持三种通配符

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

切点表达式由切点函数组成, 其中execution()是最常用的切点函数, 用来匹配方法

execution()语法🍂

注意<><>之间的空格

execution(<修饰符> <返回类型> <包.类.方法名(参数)> <异常>)
• 1

修饰符(一般省略)

省略修饰符默认是*

修饰符 含义
public 公共的
private 私有的
* 任意的

返回值类型(不能省略)

返回值类型 含义
void 无返回值类型
string 返回字符串类型
* 任意类型

含义
com.example.demo 固定包
com.example.demo.*.service demo 包下的任意子包(以 service 结尾)
com.example.demo.. demo 包下的所有子包(包含 demo 包)
com.example.demo.*.service.. demo 包下的任意子包, 固定目录 service, service 目录下的所有子包(包含 service 包)

含义
UserController 指定类
User* 以 User 开头的所有类
*troller 以 troller 结尾的所有类
* 任意类

方法名(不能省略)

方法名 含义
processu 固定方法
pro* 以 pro 开头所有方法
*ssu 以 ssu 结尾的所有方法
* 任意方法

(参数)

(参数) 含义
( ) 无参
(int) 一个整型
(int, int) 两个整形
(…) 任意参数

异常(可省略)

异常 → throws

省略表示不将异常作为匹配的条件(即忽略异常)

通常情况下不写异常

Spring AOP 的实现原理


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


未使用 Spring AOP🍂

使用 Spring AOP🍂

Spring AOP 主要基于 2 种方式实现

  • JDK
  • CGLIB

CGLIB 是 Java 中的动态代理框架, 主要作用是根据目标类和方法, 动态生成代理类

Java 中的动态代理框架, 几乎都是依赖字节码框架(例如 ASM, Javassist…)实现的

字节码框架是直接操作 class 字节码的框架. 可以加载已有的 class 字节码文件信息, 修改部分信息, 或动态生成 class

JDK 和 CGLIB 的区别🍭

  1. JDK 实现, 要求被代理类必须实现接口, 之后是通过InvocationHandlerProxy, 在运行时动态的在内存中生成了代理类对象, 该代理对象是通过实现同样的接口实现(类似静态代理接口实现的方式), 只是该代理类是在运行期时, 动态的织入统一的业务逻辑字节码来完成
  2. CGLIB 实现, 被代理类可以不实现接口, 是通过继承被代理类, 在运行时动态的生成代理类对象

🔎🌸🌸🌸完结撒花🌸🌸🌸


相关文章
|
2月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
390 0
|
1月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
6月前
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
1000 13
|
3月前
|
人工智能 监控 安全
Spring AOP切面编程颠覆传统!3大核心注解+5种通知类型,让业务代码纯净如初
本文介绍了AOP(面向切面编程)的基本概念、优势及其在Spring Boot中的使用。AOP作为OOP的补充,通过将横切关注点(如日志、安全、事务等)与业务逻辑分离,实现代码解耦,提升模块化程度、可维护性和灵活性。文章详细讲解了Spring AOP的核心概念,包括切面、切点、通知等,并提供了在Spring Boot中实现AOP的具体步骤和代码示例。此外,还列举了AOP在日志记录、性能监控、事务管理和安全控制等场景中的实际应用。通过本文,开发者可以快速掌握AOP编程思想及其实践技巧。
|
3月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
3月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
10月前
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
517 6
|
9月前
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
609 25
|
9月前
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
419 24
|
8月前
|
Java API 微服务
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——Spring Boot 中的 AOP 处理
本文详细讲解了Spring Boot中的AOP(面向切面编程)处理方法。首先介绍如何引入AOP依赖,通过添加`spring-boot-starter-aop`实现。接着阐述了如何定义和实现AOP切面,包括常用注解如`@Aspect`、`@Pointcut`、`@Before`、`@After`、`@AfterReturning`和`@AfterThrowing`的使用场景与示例代码。通过这些注解,可以分别在方法执行前、后、返回时或抛出异常时插入自定义逻辑,从而实现功能增强或日志记录等操作。最后总结了AOP在实际项目中的重要作用,并提供了课程源码下载链接供进一步学习。
965 0