当前位置: 首页 > news >正文

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 开头的方法。

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

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • macos系统内置php文件列表 系统自带php卸载方法
  • 沐渥科技:两显氮气柜和三显氮气柜要怎么选择?
  • FPGA开发:可编程逻辑器件概述
  • vue中的css深度选择器
  • 基于STM32的RTOS--freertos的使用(HAL实现多任务)
  • react 子组件调用父组件方法,获取的数据不是最新值
  • 用RNN(循环神经网络)预测股票价格
  • 前端技术(六)—— AJAX详解
  • 为什么 2!=false 和 2!=true 返回的都是true
  • Java-IO:浅谈对IO的认识
  • 【大规模语言模型:从理论到实践】Transformer中PositionalEncoder详解
  • java 给list对象根据给定条数进行分组工具类
  • 视频中的噪点怎么去除?
  • ES之三:springboot集成ES
  • JavaScript基础面试题:(第二天)
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • Android 控件背景颜色处理
  • Angular4 模板式表单用法以及验证
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • E-HPC支持多队列管理和自动伸缩
  • flask接收请求并推入栈
  • JS+CSS实现数字滚动
  • python_bomb----数据类型总结
  • Python3爬取英雄联盟英雄皮肤大图
  • 初识MongoDB分片
  • 代理模式
  • 极限编程 (Extreme Programming) - 发布计划 (Release Planning)
  • 简单基于spring的redis配置(单机和集群模式)
  • 猫头鹰的深夜翻译:JDK9 NotNullOrElse方法
  • 前端技术周刊 2019-02-11 Serverless
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • ​1:1公有云能力整体输出,腾讯云“七剑”下云端
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • ​业务双活的数据切换思路设计(下)
  • # 移动硬盘误操作制作为启动盘数据恢复问题
  • #QT(TCP网络编程-服务端)
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • $LayoutParams cannot be cast to android.widget.RelativeLayout$LayoutParams
  • (1)(1.8) MSP(MultiWii 串行协议)(4.1 版)
  • (1)常见O(n^2)排序算法解析
  • (13)DroneCAN 适配器节点(一)
  • (ros//EnvironmentVariables)ros环境变量
  • (第二周)效能测试
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (附源码)ssm基于微信小程序的疫苗管理系统 毕业设计 092354
  • (附源码)ssm学生管理系统 毕业设计 141543
  • (七)Knockout 创建自定义绑定
  • (十七)Flink 容错机制
  • (四)Android布局类型(线性布局LinearLayout)
  • (微服务实战)预付卡平台支付交易系统卡充值业务流程设计
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (原創) 博客園正式支援VHDL語法著色功能 (SOC) (VHDL)
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • .NET Core 2.1路线图