Spring boot -- 面向切面(AOP)

一、面向切面的作用

1、解耦

面向切面编程将把切面代码脱离业务进行编码,降低了代码耦合性和维护成本。

2、面向切面使用思路

当部分业务接口需要登陆的情况下才能使用,这时候就使用面向切面编程,而不是在每个接口中进行判断用户是否登录。

日志添加。开发中常见日志的记录,这时候使用面向切面思想进行编码将减少在每个方法中实现日志。

二、面向切面实现

首先得先了解@Aspect注解。

@Aspect 是 Spring AOP(Aspect-Oriented Programming,面向切面编程)中的一个关键注解。AOP 是一种编程范式,它允许程序员定义横切关注点(cross-cutting concerns),这些关注点会“切入”到应用的多个不同点中,比如日志、事务管理等。

当你使用 Spring AOP 时,你会定义一个或多个切面(Aspect),这些切面包含了多个通知(Advice),这些通知定义了何时以及如何执行横切关注点。

@Aspect 注解用于声明一个类为切面类。这个类通常会包含多个通知方法,这些方法使用如 @Before@After@AfterReturning@AfterThrowing 和 @Around 等注解来指定它们的执行时机。

以下是一个简单的例子,展示如何使用 @Aspect

javaimport org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

@Before("execution(* com.example.myapp.MyClass.myMethod(..))")
public void logBefore() {
System.out.println("Before method execution");
}
}

在这个例子中:

  • @Aspect 注解表示这个类是一个切面类。
  • @Component 注解让 Spring 知道这个类是一个 bean,需要被 Spring 容器管理。
  • @Before 注解定义了一个前置通知(Before Advice),它会在 com.example.myapp.MyClass.myMethod 方法执行之前被调用。

需要注意的是,要使 Spring AOP 工作,你还需要在 Spring 配置中启用它,通常是通过在配置类上添加 @EnableAspectJAutoProxy 注解来完成的。

此外,Spring AOP 默认是基于代理的,这意味着它只适用于单例 beans。如果你需要对原型(prototype)范围的 beans 使用 AOP,你可能需要考虑使用 AspectJ,它是一个更强大、更灵活的 AOP 实现。

execution表达式的基本语法是:

javaexecution([权限修饰符] [返回类型] [方法名]([参数列表]))

这里是一些execution表达式的例子:

  • 匹配所有方法执行:

    javaexecution(* *(..))
  • 匹配com.example包下所有类的所有方法:

    javaexecution(* com.example.*.*(..))
  • 匹配com.example包下所有类的public方法:

    javaexecution(public * com.example.*.*(..))
  • 匹配com.example.service包下所有类的返回类型为void的方法:

    javaexecution(void com.example.service.*.*(..))
  • 匹配com.example.service.UserService类的所有方法:

    javaexecution(* com.example.service.UserService.*(..))
  • 匹配com.example.service.UserService类的特定方法findUserById

    javaexecution(* com.example.service.UserService.findUserById(..))

你可以在切面类中使用@Pointcut注解来定义一个切入点,然后在通知方法中使用这个切入点:

java@Aspect
@Component
public class LoggingAspect {

@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}

@Before("serviceMethods()")
public void logBefore() {
System.out.println("Before method execution");
}
}

在这个例子中,serviceMethods切入点匹配了com.example.service包下所有类的所有方法。然后,@Before注解使用了这个切入点,意味着logBefore方法会在com.example.service包下所有方法执行之前被调用。

为了使Spring AOP生效,你还需要在Spring配置中启用AOP支持,通常是通过在配置类上添加@EnableAspectJAutoProxy注解来完成的。

三、ProceedingJoinPoint介绍

在Spring AOP(Aspect-Oriented Programming)中,ProceedingJoinPoint是一个特殊的连接点(JoinPoint),它代表一个正在被执行的方法调用,并且允许你在该方法调用之前、之后或者替换该方法的执行。ProceedingJoinPointJoinPoint的子接口,它扩展了JoinPoint的功能,允许你控制方法的执行流程。

当你定义一个环绕通知(Around Advice)时,你可以使用ProceedingJoinPoint作为通知方法的参数。这样,你就可以在通知方法内部决定是否执行目标方法,何时执行,以及如何处理目标方法的返回值或异常。

以下是一个使用ProceedingJoinPoint的环绕通知的例子:

javaimport org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

@Around("execution(* com.example.myapp.MyClass.myMethod(..))")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();

Object proceed = joinPoint.proceed(); // 执行目标方法

long executionTime = System.currentTimeMillis() - start;

System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms");
return proceed;
}
}

在这个例子中:

  • @Around注解定义了一个环绕通知,它匹配com.example.myapp.MyClass.myMethod方法的执行。
  • ProceedingJoinPoint作为logExecutionTime方法的参数,允许你在方法执行前后进行自定义操作。
  • joinPoint.proceed()调用实际执行了目标方法。
  • 在调用proceed()方法之前和之后,你可以添加自定义的逻辑,比如记录开始时间、计算执行时间等。

注意,使用ProceedingJoinPoint时,你不能简单地调用目标方法,而是需要通过proceed()方法。如果你直接调用目标方法,那么环绕通知将不会起作用,因为它会绕过AOP的代理机制。

另外,为了使Spring AOP工作,你需要在Spring配置中启用AOP支持,通常是通过在配置类上添加@EnableAspectJAutoProxy注解来完成的。同时,确保你的切面类(在这个例子中是LoggingAspect)被Spring容器管理,通常是通过添加@Component注解来完成的。

  • 13
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值