Spring AOP

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Spring AOP

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

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

AOP 的作用

在程序运行期间, 在不改变源代码的基础上, 对已有方法进行增强 (无侵入性: 解耦)

AOP 的常见用途

  • 统一日志思想
  • 统一执行方法计时
  • 事务的开启和提交
  • 统一数据返回格式
  • 统一异常处理

Spring AOP

Spring AOP 是 AOP 思想的一种实现

AOP 思想有很多实现 : Spring Boot 统一功能处理 , Spring AOP , AspectJ , CGLIB …

Spring AOP 的实现方式


  1. 基于注解 @Aspect 实现 (常用)
  2. 基于 Spring API (xml 文件) 方式实现
  3. 基于代理实现

Spring Boot 统一功能处理 和 Spring AOP

Spring Boot 统一功能处理 和 Spring AOP 是 相辅相成 的技术

像拦截器作用维度是 url(一次请求和响应), @ControllerAdvice 的应用场景主要是全局异常处理, 数据绑定, 数据预处理.

Spring AOP 的作用维度则可以更加细致 (包, 类, 方法, 参数 …), 能够实现更复杂的业务逻辑

Spring AOP:

Spring AOP 是 Spring 框架的一个模块,用于支持面向切面编程。它通过在方法执行前、执行后或抛出异常时动态地添加横切逻辑,例如日志记录、性能监控、事务管理等。AOP 的主要目的是在不修改原始代码的情况下,通过将横切逻辑与业务逻辑分离,提高代码的模块性和可维护性。

Spring Boot:

Spring Boot 是 Spring 框架的一个扩展,旨在简化基于 Spring 的应用程序的开发和部署。它提供了自动配置、快速构建、嵌入式服务器等特性,使得开发者可以更加便捷地创建独立的、生产级别的 Spring 应用程序。

功能统一处理:

在实际应用中,Spring AOP 可以用于统一处理某些横切关注点,如日志记录、权限控制等,而 Spring Boot 可以用于统一处理应用程序的配置、异常处理、安全性等方面的功能。因此,虽然 Spring AOP 和 Spring Boot 在实现功能统一处理上有一定的重叠,但它们更多地是在不同层面上为应用程序提供支持,而不是直接相关的概念或功能模块。

综上所述,Spring AOP 和 Spring Boot 都可以用于实现功能的统一处理,但它们是不同的模块,各自在不同的层面提供支持,没有直接的关联关系。


Spring AOP 的原理

Spring AOP 基于 动态代理 实现

代理模式(委托模式)

想了解动态代理, 就得先了解代理模式

代理模式 : 为其他对象提供一种代理, 以控制对这个对象的访问. 它的作用是通过一个代理类, 让我们在调用目标方法的时候, 不再是直接调用目标方法 (有可能参数不适配, 返回值不准确 …) , 而是通过调用代理类, 代理类里面再调用目标方法的方式, 间接调用

代理模式主要角色

  1. Subject : 业务接口类. (不一定有)
  2. RealSubject : 业务实现类. 具体的业务执行, 即被代理对象
  3. Proxy : 代理类

代理模式分类


代理模式分为静态代理和动态代理


静态代理 : 在程序运行期代理类的 .class 文件已经存在, 是被写死不能修改的代理

动态代理 : 在程序运行时, 运用 反射机制 动态创建而成的代理

Java 中动态代理有两种实现: JDK 动态代理 & CGBIG 动态代理

JDK 动态代理, 只能代理接口, 不能代理普通类

CGLIB 动态代理, 能够代理接口和普通类

什么时候使用什么代理?

Spring AOP 中, 两种动态代理模式都使用了, 具体使用哪种方式, 还是依据 版本和配置 实现:

  • 在配置文件中, 通过属性 proxyTargetClass 设置使用哪种代理方式
  • Spring Boot 2.X 版本 之前, 该属性默认为 false, 即目标对象实现接口, 则使用 jdk 静态代理, 目标方法未实现接口 (只有实现类), 则使用 cglib 动态代理
  • Spring Boot 2.X 版本 之后, 该属性默认为 true, 无论目标对象是否实现接口, 都使用 cglib 动态代理

基于 @Aspect 注解实现 Spring AOP

首先要引入依赖

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

使用 Spring AOP 编写, 对调用的方法计时操作

@Slf4j
@Component
@Aspect
public class SpringAOP {
    @Pointcut("execution(* com.zrj.mybatisreview.*.*(..))")
    public void pt(){}

    //@Around("execution(* com.zrj.mybatisreview.*.*(..))")
    @Around("pt()")
    public Object recordTime(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        // 使用该方法记录 每个方法被调用的时长
        // 记录方法执行开始时间
        long begin = System.currentTimeMillis();
        // 执行原始方法
        Object result = proceedingJoinPoint.proceed();
        // 记录方法执行结束时间
        long end = System.currentTimeMillis();
        // 日志打印方法执行时长
        log.info(proceedingJoinPoint.getSignature() + "执行耗时: {}ms", end - begin);
        // 返回原始方法运行结果 (不返回运行结果, 就相当于代码没执行 ...)
        return result;
    }
    
    @Before("pt()")
    public void beforeAOP() {
        log.info("hello world!");
    }
}


Spring AOP 中的一些概念

切点(Pointcut)

也叫做 “切入点”

切点就是 一组规则 (好抽象), 通过切点表达式, 告诉程序应该对哪些方法进行功能增强

@Pointcut 提取出公共的切点表达式, 可供重复使用

连接点(Join Point)

满足切面表达式规则的所有方法, 都成为连接点

可以理解为: 切点是保存了众多连接点的一个集合

通知(Advice)

通知就是具体要做的内容, 指哪些重复的逻辑, 也就是共性功能

上述代码为例就是对每个方法进行计时操作, 并打印日志

切面(Aspect)

切面 = 切点 + 通知

通过切点能够描述出 AOP 的作用范围, 通知则告诉 对切点具体要执行的操作

切面即包含了通知逻辑的定义, 也包含了连接点的定义

切面所在的类, 一般称为 切面类 (被 @Aspect 注解标注的类)

一个切面类可以包含多个切点


切面优先级 @Order

  • 使用场景: 多切面, 且具有 相同类型 通知情况下, 指定不同通知的执行顺序
  • 数字越小, 优先级越高, 同种类型通知, 先执行优先级高的, 在执行优先级低的


Spring AOP 的通知类型

@Around : 环绕通知

@Before : 前置通知

@After : 后置通知

@AfterReturning : 返回后通知

@AfterThrowing : 异常后通知

通知执行顺序

通知注意事项

  • @Around 环绕通知需要主动调用 proceedingJoinPoint.proceed() 方法来让原始方法执行, 其他通知则不需要考虑目标方法的执行
  • @Around 环绕通知方法的返回值, 必须指定为 Object 类型, 来接受原始方法的返回值, 否则原始方法执行完毕, 是获取不到返回值的

切点表达式

  1. execution() : 根据方法签名来 定义切点规则
  1. @annotation() : 根据注解来匹配 定义切点规则

execution()

execution() 是最常见的切点表达式, 用来匹配方法, 语法为:

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

切点表达式支持通配符匹配

  • * 匹配任意一个元素
  • .. 匹配任意个元素

@annotation

@annotation 常用来匹配多个无规则方法

(一个类中一部分方法需要匹配, 一部分方法不需要匹配, 此时再使用 execution() 就不太方便了)

@annotation 使用流程

  1. 编写自定义注解 (如果使用本来就有的注解 [eg: @Controller], 可以省略这一步)
  2. 使用 @annotation 表达式来描述切点
  3. 再连接点的方法上添加自定义注解
// 注解类代码

package com.zrj.mybatisreview;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeRecord {
    // 使用本注解对需要进行计时的方法进行标注
}
// 切面类代码

@Slf4j
@Aspect
@Component
public class TimeRecord {
  // @annotation() 中的参数是注解的位置(包名.注解名)
    @Before("@annotation(com.zrj.mybatisreview.TimeRecord)") 
    public void before() {
        log.info("TimeRecord -> begin");
    }

    @After("@annotation(com.zrj.mybatisreview.TimeRecord)")
    public void after() {
        log.info("TimeRecord -> after");
    }
}

对想要计时的方法添加 自定义注解, 该方法就会在调用的时候自动执行 AOP 逻辑

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
2月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
402 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的工作原理与实现细节。
1017 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代理。通过源码分析可深入了解其实现细节,优化应用功能。
522 6
|
9月前
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
617 25
|
9月前
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
426 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在实际项目中的重要作用,并提供了课程源码下载链接供进一步学习。
979 0

热门文章

最新文章