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

相关文章

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

Java操作Word文档的全面指南

《Java操作Word文档的全面指南》在Java开发中,操作Word文档是常见的业务需求,广泛应用于合同生成、报表输出、通知发布、法律文书生成、病历模板填写等场景,本文将全面介绍Java操作Word文... 目录简介段落页头与页脚页码表格图片批注文本框目录图表简介Word编程最重要的类是org.apach

Spring Boot中WebSocket常用使用方法详解

《SpringBoot中WebSocket常用使用方法详解》本文从WebSocket的基础概念出发,详细介绍了SpringBoot集成WebSocket的步骤,并重点讲解了常用的使用方法,包括简单消... 目录一、WebSocket基础概念1.1 什么是WebSocket1.2 WebSocket与HTTP

SpringBoot+Docker+Graylog 如何让错误自动报警

《SpringBoot+Docker+Graylog如何让错误自动报警》SpringBoot默认使用SLF4J与Logback,支持多日志级别和配置方式,可输出到控制台、文件及远程服务器,集成ELK... 目录01 Spring Boot 默认日志框架解析02 Spring Boot 日志级别详解03 Sp

java中反射Reflection的4个作用详解

《java中反射Reflection的4个作用详解》反射Reflection是Java等编程语言中的一个重要特性,它允许程序在运行时进行自我检查和对内部成员(如字段、方法、类等)的操作,本文将详细介绍... 目录作用1、在运行时判断任意一个对象所属的类作用2、在运行时构造任意一个类的对象作用3、在运行时判断

java如何解压zip压缩包

《java如何解压zip压缩包》:本文主要介绍java如何解压zip压缩包问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java解压zip压缩包实例代码结果如下总结java解压zip压缩包坐在旁边的小伙伴问我怎么用 java 将服务器上的压缩文件解压出来,

SpringBoot中SM2公钥加密、私钥解密的实现示例详解

《SpringBoot中SM2公钥加密、私钥解密的实现示例详解》本文介绍了如何在SpringBoot项目中实现SM2公钥加密和私钥解密的功能,通过使用Hutool库和BouncyCastle依赖,简化... 目录一、前言1、加密信息(示例)2、加密结果(示例)二、实现代码1、yml文件配置2、创建SM2工具

Spring WebFlux 与 WebClient 使用指南及最佳实践

《SpringWebFlux与WebClient使用指南及最佳实践》WebClient是SpringWebFlux模块提供的非阻塞、响应式HTTP客户端,基于ProjectReactor实现,... 目录Spring WebFlux 与 WebClient 使用指南1. WebClient 概述2. 核心依

Spring Boot @RestControllerAdvice全局异常处理最佳实践

《SpringBoot@RestControllerAdvice全局异常处理最佳实践》本文详解SpringBoot中通过@RestControllerAdvice实现全局异常处理,强调代码复用、统... 目录前言一、为什么要使用全局异常处理?二、核心注解解析1. @RestControllerAdvice2

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注