Spring AOP的快速入门与应用

概述

AOP 意为面向特定的方法编程

一个例子来引入

@Slf4j
@Component
@Aspect //AOP类
public class TimeAspect {
    @Around("execution(* com.sky.service.impl.*.*(..))")
    public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable{
        //记录开始时间
        long beginTime = System.currentTimeMillis();
        //调用原始方法运行
        Object result = joinPoint.proceed();
        //记录结束时间
        long endTime = System.currentTimeMillis();
        log.info("方法运行时间:{}",endTime - beginTime);

        return result;
    }
}

这个代码借助了AOP来统计了service层的接口或者类的运行时间,而不用修改原始代码。

AOP核心概念

  • 连接点:JoinPoint,可以被AOP控制的办法,包含着方法执行时的相关信息

  • 通知:Advice,指哪些重复的逻辑,也就是共性功能

  • 切入点:PointCut,匹配连接点的条件,通知仅会在切入点方法执行时被应用

  • 切面:Aspect,描述通知与切入点的对应关系

  • 目标对象:Target,通知所应用的对象

通知类型

  • @Around:环绕通知,此注解标注的通知方法在目标方法前、后都被执行

  • @Before:前置通知,此注解标注的通知方法在目标方法前被执行

  • @After :后置通知,此注解标注的通知方法在目标方法后被执行,无论是否有异常都会执行

  • @AfterReturning:返回后通知,此注解标注的通知方法在目标方法后被执行,有异常不会执行

  • @AfterThrowing :异常后通知,此注解标注的通知方法发生异常后执行

通知顺序

目标方法前的通知方法:字母排名越靠前,越先执行

目标方法后的通知方法:字母排名越靠后,越先执行

切入点表达式

用来决定项目中的哪些方法需要加入通知

execution():根据方法的签名来匹配

语法是:execution(访问修饰符 返回值 包名.类名.方法名(方法参数)throws 异常)

可以省略异常、访问修饰符、包名.类名

通配符

  • * :单个独立的任意符号,可以通配任意返回值、包名、类名、方法名、任意类型的一个参数,也可以通配包、类、方法名的一部分

比如execution(*com.*.service.*.update*(*)) 五个*号依次对应:任意类型的返回值、任意的第二级包、service下的任意的接口或者类、任意以update开头的方法并且是一个参数

  • .. :多个连续的任意符号,可以通配任意层级的包,或任意类型、任意个数的参数

主要用于匹配方法的任意个数的参数

@annotation 切入点表达式,用于匹配标识有特定注解的方法。

@annotation(全类名),然后再通知方法添加@类名 这个注解即可

连接点

在Spring中用JoinPoint抽象了连接点,用它可以获得方法执行时的相关信息,如目标类名、方法名、方法参数等。

对于 @Around 通知,获取连接点信息只能使用ProceedingJoinPoint

对于其他四种通知,获取连接点信息只能使用 JoinPoint,它是 ProceedingJoinPoint 的父类型

String className = joinPoint.getTarget().getclass().getName();//获取目标类名

Signature signature = joinPoint.getsignature();//获取目标方法签名

String methodName = joinPoint.getsignature().getName();//获取目标方法名

Object[]args = joinPoint.getArgs();//获取目标方法运行参数

Object result= joinPoint.proceed(); //放行目标方法
return result;


Comment