springboot提升-切面编程

2024-09-06 05:36

本文主要是介绍springboot提升-切面编程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 开发步骤
      • 1. 引入依赖
      • 2. 创建切面类
        • 示例切面类:
      • 3. 定义切入点表达式
        • 示例切入点表达式:
      • 4. 使用注解定义通知
        • 示例通知:
      • 5. 自动装配切面类
      • 6. 测试切面功能
      • 注意事项
    • 切面注解
      • 常用的切面注解
      • 示例代码
      • 注意事项
    • 切面语法
      • 示例 1: 匹配特定的方法
      • 示例 2: 匹配所有公共方法
      • 示例 3: 匹配所有方法
      • 示例 4: 匹配特定包下的所有方法
      • 示例 5: 匹配具有特定参数的方法
      • 示例 6: 匹配特定返回类型的方法
      • 示例 7: 匹配没有参数的方法
      • 示例 8: 匹配特定异常的方法
      • 示例 9: 匹配特定方法签名

开发步骤

在 Spring Boot 中使用切面(Aspect)开发可以帮助你在不修改现有业务逻辑的情况下,增加诸如日志记录、安全检查、性能监控等功能。Spring 提供了 Spring AOP(面向切面编程)的支持,它允许你定义切面来封装横切关注点(cross-cutting concerns),并通过通知(advice)来增强程序的功能。

以下是如何在 Spring Boot 中使用切面开发的基本步骤:

1. 引入依赖

确保你的项目包含 Spring AOP 的依赖。如果你使用的是 Spring Boot,则默认已经包含了 Spring AOP 的支持,因此无需额外添加依赖。

2. 创建切面类

创建一个切面类,并使用 @Aspect 注解标记它。在这个类中定义通知(Advice)方法,这些方法将在特定的连接点(join point)执行。

示例切面类:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class);@Pointcut("execution(* com.example.service.*.*(..))")public void loggingPointcut() {// 无具体实现,仅作为切入点定义}@Before("loggingPointcut()")public void logBefore(JoinPoint joinPoint) {logger.info("Entering method: {}.{} with arguments: {}",joinPoint.getSignature().getDeclaringTypeName(),joinPoint.getSignature().getName(),joinPoint.getArgs());}@After("loggingPointcut()")public void logAfter(JoinPoint joinPoint) {logger.info("Exiting method: {}.{}",joinPoint.getSignature().getDeclaringTypeName(),joinPoint.getSignature().getName());}
}

在这个例子中,我们定义了一个名为 loggingPointcut 的切入点,它匹配 com.example.service 包下所有类的所有方法。logBefore 方法会在切入点匹配的方法执行前被调用,而 logAfter 方法则在方法执行后被调用。

3. 定义切入点表达式

在切面类中定义切入点表达式(pointcut expression),它可以指定何时执行通知。Spring 支持多种类型的切入点表达式,包括但不限于方法执行、异常抛出等。

示例切入点表达式:
@Pointcut("execution(* com.example.service.*.*(..))")
public void loggingPointcut() {// 无具体实现,仅作为切入点定义
}

这个表达式定义了一个名为 loggingPointcut 的切入点,它匹配 com.example.service 包下所有类的所有方法。

4. 使用注解定义通知

使用 @Before@After@Around@AfterReturning@AfterThrowing 等注解来定义不同类型的通知。

示例通知:
@Before("loggingPointcut()")
public void logBefore(JoinPoint joinPoint) {// 在切入点匹配的方法执行前的操作
}@After("loggingPointcut()")
public void logAfter(JoinPoint joinPoint) {// 在切入点匹配的方法执行后的操作
}

5. 自动装配切面类

在 Spring Boot 中,由于使用了组件扫描 (@ComponentScan),所以只需要将切面类标注为 @Component,Spring 就会自动检测并装配它们。如果你没有使用组件扫描,也可以显式地在配置类中声明切面。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class AppConfig {@Beanpublic LoggingAspect loggingAspect() {return new LoggingAspect();}
}

6. 测试切面功能

编写单元测试来验证切面是否按预期工作。你可以编写一些测试用例来触发被切面增强的方法,并检查日志输出是否符合预期。

注意事项

  • 确保切入点表达式正确无误,否则通知可能不会在预期的位置执行。
  • 谨慎使用 @Around 通知,因为它可以完全控制方法的执行流程,容易引起死锁或其他问题。
  • 如果有多个切面,需要注意它们之间的顺序,可以通过 Ordered 接口来控制顺序。

通过以上步骤,你可以在 Spring Boot 中成功地实现切面开发,从而在不侵入现有业务代码的情况下增加新的功能。

切面注解

在 Spring Boot 中,使用切面(Aspect)来进行面向切面编程(AOP)可以通过一系列注解来定义和配置切面的行为。以下是 Spring AOP 中常用的几个注解及其用途:

常用的切面注解

  1. @Aspect

    • 用于标记一个类是一个切面类。
    • 这个类将包含多个通知(Advice)方法,这些方法会在特定的连接点(Join Point)处被调用。
  2. @Component

    • 将切面类注册为 Spring Bean,确保切面类能够被 Spring 容器管理。
    • 通常与 @Aspect 结合使用。
  3. @Before

    • 用于在目标方法执行前执行通知方法。
    • 如果 @Before 通知方法抛出了异常,则不会执行目标方法。
  4. @After

    • 用于在目标方法执行后执行通知方法,无论方法是否成功执行或抛出异常。
    • 这个通知总是会被执行,除非它自己抛出了一个未处理的异常。
  5. @AfterReturning

    • 用于在目标方法成功完成后执行通知方法。
    • 如果目标方法抛出了异常,则此通知不会被执行。
  6. @AfterThrowing

    • 用于在目标方法抛出异常后执行通知方法。
    • 只有当目标方法抛出异常时,此通知才会被执行。
  7. @Around

    • 用于在目标方法执行前后都执行通知方法,可以用来实现环绕通知,如性能监视等。
    • 这种通知可以决定是否继续执行目标方法或直接返回或抛出异常。

示例代码

下面是一个简单的示例,展示了如何使用这些注解来定义一个切面:

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {// 定义一个切入点表达式,用于匹配特定的方法调用@Pointcut("execution(* com.example.demo.service.*.*(..))")public void serviceLayerExecution() {}// 在切入点处执行前置通知@Before("serviceLayerExecution()")public void logBefore(JoinPoint joinPoint) {System.out.println("Executing @Before advice on method: " + joinPoint.getSignature());}// 在切入点处执行后置通知@After("serviceLayerExecution()")public void logAfter(JoinPoint joinPoint) {System.out.println("Executing @After advice on method: " + joinPoint.getSignature());}// 在切入点处执行返回通知@AfterReturning(pointcut = "serviceLayerExecution()", returning = "result")public void logAfterReturning(JoinPoint joinPoint, Object result) {System.out.println("Executing @AfterReturning advice on method: " + joinPoint.getSignature() + ", result: " + result);}// 在切入点处执行异常通知@AfterThrowing(pointcut = "serviceLayerExecution()", throwing = "exception")public void logAfterThrowing(JoinPoint joinPoint, Exception exception) {System.out.println("Executing @AfterThrowing advice on method: " + joinPoint.getSignature() + ", exception: " + exception.getMessage());}
}

在这个示例中,我们定义了一个名为 LoggingAspect 的切面类,它包含了四种不同的通知方法,分别对应四种不同的通知类型:@Before@After@AfterReturning@AfterThrowing。这些方法会在切入点表达式 serviceLayerExecution() 指定的方法调用前后执行相应的逻辑。

注意事项

  • 确保你的 Spring Boot 应用已启用 AOP 支持,通常情况下,如果切面类上有 @Aspect@Component 注解,那么 Spring Boot 会自动识别并配置 AOP 支持。
  • 为了确保切面能够正常工作,确保切入点表达式正确无误,并且覆盖了你希望拦截的方法。
  • 考虑到性能和可维护性,尽量减少切面的复杂度,并保持切面逻辑的单一职责原则。

切面语法

在 Spring AOP 中,execution 是一个切入点表达式,用于指定哪些连接点(即方法调用)应该被切面所关注。execution 表达式允许你根据方法签名来匹配方法调用,包括返回类型、包、类、方法名以及参数列表。

execution 表达式的语法格式如下:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)

其中:

  • modifiers-pattern?:可选的修饰符模式。
  • ret-type-pattern:返回类型模式。
  • declaring-type-pattern?:可选的声明类型模式。
  • name-pattern:方法名模式。
  • param-pattern:参数模式。
  • throws-pattern?:可选的异常模式。

下面是一些具体的例子:

示例 1: 匹配特定的方法

execution(public int com.example.demo.service.MyService.myMethod(int))

这将匹配 com.example.demo.service.MyService 类中的 myMethod 方法,该方法有一个 int 类型的参数并且返回 int 类型的结果。

示例 2: 匹配所有公共方法

execution(public * *(..))

这将匹配所有公共方法,无论其返回类型或参数列表是什么。

示例 3: 匹配所有方法

execution(* *.*(..))

这将匹配所有方法,无论其返回类型、方法名称、所在类或参数列表。

示例 4: 匹配特定包下的所有方法

execution(* com.example.demo.service.*.*(..))

这将匹配 com.example.demo.service 包下所有类的所有方法。

示例 5: 匹配具有特定参数的方法

execution(* com.example.demo.service.*.*(*String*, ..))

这将匹配 com.example.demo.service 包下所有类的所有方法,只要其中一个参数是 String 类型即可。

示例 6: 匹配特定返回类型的方法

execution(String *.*(..))

这将匹配所有返回类型为 String 的方法。

示例 7: 匹配没有参数的方法

execution(* *.*() throws ..)

这将匹配所有没有参数的方法,并且允许方法抛出异常。

示例 8: 匹配特定异常的方法

execution(* *.*(..) throws java.io.IOException)

这将匹配所有可能抛出 java.io.IOException 异常的方法。

示例 9: 匹配特定方法签名

execution(* com.example.demo.service.*.get*(..))

这将匹配 com.example.demo.service 包下所有类的任何以 get 开头的方法。

使用这些表达式可以帮助你精确地控制哪些方法会被切面所影响。在编写切入点表达式时,请确保它们足够具体,以避免意外地匹配到其他你不希望影响的方法。

这篇关于springboot提升-切面编程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1141142

相关文章

Spring Boot循环依赖原理、解决方案与最佳实践(全解析)

《SpringBoot循环依赖原理、解决方案与最佳实践(全解析)》循环依赖指两个或多个Bean相互直接或间接引用,形成闭环依赖关系,:本文主要介绍SpringBoot循环依赖原理、解决方案与最... 目录一、循环依赖的本质与危害1.1 什么是循环依赖?1.2 核心危害二、Spring的三级缓存机制2.1 三

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

SpringBoot集成Milvus实现数据增删改查功能

《SpringBoot集成Milvus实现数据增删改查功能》milvus支持的语言比较多,支持python,Java,Go,node等开发语言,本文主要介绍如何使用Java语言,采用springboo... 目录1、Milvus基本概念2、添加maven依赖3、配置yml文件4、创建MilvusClient

浅析Java中如何优雅地处理null值

《浅析Java中如何优雅地处理null值》这篇文章主要为大家详细介绍了如何结合Lambda表达式和Optional,让Java更优雅地处理null值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录场景 1:不为 null 则执行场景 2:不为 null 则返回,为 null 则返回特定值或抛出异常场景

SpringMVC获取请求参数的方法

《SpringMVC获取请求参数的方法》:本文主要介绍SpringMVC获取请求参数的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下... 目录1、通过ServletAPI获取2、通过控制器方法的形参获取请求参数3、@RequestParam4、@

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

SpringBoot应用中出现的Full GC问题的场景与解决

《SpringBoot应用中出现的FullGC问题的场景与解决》这篇文章主要为大家详细介绍了SpringBoot应用中出现的FullGC问题的场景与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录Full GC的原理与触发条件原理触发条件对Spring Boot应用的影响示例代码优化建议结论F

springboot项目中常用的工具类和api详解

《springboot项目中常用的工具类和api详解》在SpringBoot项目中,开发者通常会依赖一些工具类和API来简化开发、提高效率,以下是一些常用的工具类及其典型应用场景,涵盖Spring原生... 目录1. Spring Framework 自带工具类(1) StringUtils(2) Coll

SpringBoot条件注解核心作用与使用场景详解

《SpringBoot条件注解核心作用与使用场景详解》SpringBoot的条件注解为开发者提供了强大的动态配置能力,理解其原理和适用场景是构建灵活、可扩展应用的关键,本文将系统梳理所有常用的条件注... 目录引言一、条件注解的核心机制二、SpringBoot内置条件注解详解1、@ConditionalOn

通过Spring层面进行事务回滚的实现

《通过Spring层面进行事务回滚的实现》本文主要介绍了通过Spring层面进行事务回滚的实现,包括声明式事务和编程式事务,具有一定的参考价值,感兴趣的可以了解一下... 目录声明式事务回滚:1. 基础注解配置2. 指定回滚异常类型3. ​不回滚特殊场景编程式事务回滚:1. ​使用 TransactionT