spring-aspectj的几个aop注解

通知(Advice)类型的说明

@Before 前置通知(Before advice) :在某连接点(JoinPoint)——核心代码(类或者方法)之前执行的通知,但这个通知不能阻止连接点前的执行。为啥不能阻止线程进入核心代码呢?因为@Before注解的方法入参不能传ProceedingJoinPoint,而只能传入JoinPoint。要知道从aop走到核心代码就是通过调用ProceedingJionPoint的proceed()方法。而JoinPoint没有这个方法。
这里牵扯区别这两个类:Proceedingjoinpoint 继承了 JoinPoint 。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法。暴露出这个方法,就能支持 aop:around 这种切面(而其他的几种切面只需要用到JoinPoint,这跟切面类型有关), 能决定是否走代理链还是走自己拦截的其他逻辑。建议看一下 JdkDynamicAopProxy的invoke方法,了解一下代理链的执行原理。这样你就能明白 proceed方法的重要性。

@After 后通知(After advice) :当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。

@AfterReturning 返回后通知(After return advice) :在某连接点正常完成后执行的通知,不包括抛出异常的情况。

@Around 环绕通知(Around advice) :包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。这时aop的最重要的,最常用的注解。用这个注解的方法入参传的是ProceedingJionPoint pjp,可以决定当前线程能否进入核心方法中——通过调用pjp.proceed();

@AfterThrowing 抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。

advice(通知)注解的执行先后顺序

这里说下简单情况——针对一个方法只被一个aspect类拦截时,aspect类内部的 advice 将按照以下的顺序进行执行情况如下:
这里写图片描述在这里插入图片描述
在这里插入图片描述

在aop中校验不通过如何不让程序进入核心代码?

通过aop中注解的执行的先后顺序我们知道,校验发生在核心代码前面的只剩下两个——@Before,@Around。
@Before : 这个注解只有在异常时才不会走核心方法——连接点。正常@Before无法阻止当前线程进入连接点。
@Around : 这个注解在连接点前后执行。并且注解的方法传入的ProceedingJionPoint 类中封装的代理方法proceed()可以让当前线程从aop方法转到连接点——核心代码方法。所以一般我们用这个注解,如果aop的安全校验不通过,则不调用proceed()方法,就永远不会进入连接点。
除此外,要注意除了Around注解的方法可以传ProceedingJionPoint 外,别的几个都不能传这个类。但是普通的数据类型是不限制的。注解的方法的返回值也不限制,可以自由限制。

举例

@Aspect
@Component
@Slf4j
public class GlobalExceptionLogAop {

    @Pointcut("execution(* org..controller..*.*(..))")
    public void point() {

    }

    @AfterThrowing(pointcut = "point()", throwing = "e")
    public void afterThrowing(Throwable e) {
        log.info("afterThrowing");
        if (e instanceof BizException) {
            log.warn(e.getMessage());
        } else {
            log.error(e.getMessage(), e);
        }
    }

    @Before(value = "point()")
    public void before() {
        log.info("before");
    }

    @After(value = "point()")
    public void after() {
        log.info("after");
    }

    @Around(value = "point()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        log.info("around-begin");
        Object o = pjp.proceed();

        log.info("around-end");
        return o;
    }

    @AfterReturning(value = "point()")
    public void afterReturning() {
        log.info("afterReturning");
    }
}


    /**
     * http://localhost:8080/user/aop
     */
    @GetMapping("aop")
    public Object aop(UserQuery query) {
        if (query.getToken() == null) {
            throw new BizException(1, "token缺失");
        }
        return Result.ok();
    }

正常情况:
在这里插入图片描述
和上图一样

异常情况:
在这里插入图片描述
和上图不一样,异常前面和正常相同,around-before,before都是必经过的。
区别是不经过around-end正常结束,而是立即结束,但是结束必须经过after,这点和正常情况相同。
after之后,不经过afterReturning,而是经过afterThrowing

图是对的,我的示例代码错了,around应该try-finally包起来,around-end放在finally中,就可打印出来了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值