Spring AOP讲解(Pointcut、Before、Around、AfterReturning、After)

AOP依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

@Pointcut

定义切入点,有以下2种方式:

方式一:设置为注解@LogFilter1标记的方法,有标记的方法触发该AOP,没有标记就没有。

@Aspect
@Component
public class LogFilter1Aspect {
	@Pointcut(value = "@annotation(com.train.aop.annotation.LogFilter1)")
	public void pointCut(){
	
	}
}

附上LogFilter1代码:

@Target(ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface LogFilter1 {
}

对应的Controller方法如下,手动添加@LogFilter1注解:

@RestController
public class AopController {

	@RequestMapping("/aop")
	@LogFilter1
	public String aop(){
	    System.out.println("这是执行方法");
	    return "success";
	}
}

方式二:采用表达式批量添加切入点,如下方法,表示AopController下的所有public方法都添加LogFilter1切面

@Pointcut(value = "execution(public * com.train.aop.controller.AopController.*(..))")
public void pointCut(){

}

@Around

环绕通知,可以说是使用最频繁的方式,会将整个方法包围起来

@Around(value = "pointCut()")
public Object round(ProceedingJoinPoint joinPoint){
    System.out.println("1、Round begin");
    Object obj = null;
    try {
        obj = joinPoint.proceed();
    } catch (Throwable throwable) {
        throwable.printStackTrace();
    }
    System.out.println("1、Round end");
    return obj;
}

@Before

前置方法,在目标方法执行前触发

@Before(value = "pointCut()")
public void before(){
    System.out.println("1、Before");
}

@After

后置方法,与@Before相反,在目标方法执行完毕后执行

@After(value = "pointCut()")
public void after(){
    System.out.println("1、After");
}

@AfterReturning

后置通知,在将返回值返回时执行

@AfterReturning(value = "pointCut()", returning = "result")
public void afterReturning(Object result){
    System.out.println("1、AfterReturning");
}

测试

接下来执行最开始声明的AopController,输出如下:

1、Round begin
1、Before
这是执行方法
1、Round end
1、After
1、AfterReturning

由此可见,AOP的顺序是:

  1. 首先进入Around
  2. 执行joinPoint.proceed()之前,触发Before
  3. 然后执行joinPoint.proceed()
  4. 执行joinPoint.proceed()之后,触发After
  5. 最后触发AfterReturning

多个AOP执行顺序

当创建了多个自定义注解,并标记到同一个方法上,可以通过设置Order来指定执行顺序。
这边创建一个LogFilter2、LogFilter2Aspect,代码跟上面的例子一样,把“1”改成“2”就行

方式一:添加注解@Order

@Aspect
@Component
@Order(1)
public class LogFilter1Aspect {
}
@Aspect
@Component
@Order(2)
public class LogFilter2Aspect {
}

方式二:实现Ordered接口

@Aspect
@Component
public class LogFilter1Aspect implements Ordered {

    @Override
    public int getOrder() {
        return 1;
    }
}
@Aspect
@Component
public class LogFilter2Aspect implements Ordered {

    @Override
    public int getOrder() {
        return 2;
    }
}

在Controller代码把2个注解都加上:

@RequestMapping("/aop")
@LogFilter1
@LogFilter2
public String aop(){
    System.out.println("这是执行方法");
    return "success";
}

执行结果如下:

1、Round begin
1、Before
2、Round begin
2、Before
这是执行方法
2、Round end
2、After
2、AfterReturning
1、Round end
1、After
1、AfterReturning

由此可见,Order越小的越优先执行,但是,After方法反而越后面执行,用一张图表示
在这里插入图片描述

1、外层的是LogFilter1,因为Order设置为1,最小优先进入
2、里层的是LogFilter2,因为Order设置为2,所以在LogFilter1后面执行
3、出来的时候,先穿过的是LogFilter2,然后才穿过LogFilter1,这也就是为什么LogFilter2的After方法会先执行
4、用一句话来形容,就是层层包围,层层嵌套

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

°Fuhb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值