SpringBoot 基于 @Aspect 的aop实现

废话不多说,直接上教程。

1.pom

        
        
        
            aopalliance
            aopalliance
            1.0
        
        
        
            aspectj
            aspectjweaver
            1.5.4
        

2.aop通知类编写

切点表达式不会写的参考这篇文章: https://blog.csdn.net/yangshangwei/article/details/77627825

这里我编写一个  ControllerAspect 类,来对我的一个  controller 包下的所有的类的方法进行通知。

包含:

  • @After
  • @Before
  • @Around
  • @AfterReturning
  • @AfterThrowing

直接上代码,代码里面的 @Pointcut 定义切点我在 spring in action 上看的是可行的,但是我代码里面报错,有大神知道为什么欢迎指点。

刚才测试了下,发现 环绕通知和其他的 前置后置一起用可能会有问题。这个注意下。

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import java.util.Arrays;

@Aspect
public class ControllerAspect {

//    @Pointcut(" ")
//    public void controllerAspect(){}

    /**
     * 前置通知
     * @param jp
     */
    @Before(" execution(* com.zzq.controller.*.*(..)) ")
    public void before(JoinPoint jp){
        String methodName = jp.getSignature().getName();
        System.out.println("【前置通知】the method 【" + methodName + "】 execution with " + Arrays.asList(jp.getArgs()));
    }

    /**
     * 后置通知
     * @param jp
     */
    @After(" execution(* com.zzq.controller.*.*(..)) ")
    public void after(JoinPoint jp  ){
        System.out.println("【后置通知】the method【"+ jp.getSignature().getName() +"】 execution done");
    }

    /**
     * 环绕通知,ProceedingJoinPoint 参数必须要,并且要放行,不然方法就处于阻塞状态
     * @param pjp
     */
//    @Around(" execution(* com.zzq.controller.*.*(..)) ")
//    public void around(ProceedingJoinPoint pjp){
//        try{
//            String methodName = pjp.getSignature().getName();
//            System.out.println("【环绕通知的前置通知】the method execution with...");
//            // 放行,不放行方法调用会处于阻塞状态
//            pjp.proceed();
//            System.out.println("【环绕通知的后置通知】the method execution done " );
//        }catch (Throwable e){
//            System.out.println("【环绕通知的异常通知】exception:" + e.getMessage() );
//        }
//    }

    /**
     * 方法执行完了之后执行,跟上返回值
    * @param jp
     * @param result
     */
    @AfterReturning(pointcut = " execution(* com.zzq.controller.*.*(..)) " , returning = "result")
    public void afterReturning(JoinPoint jp, Object result){
        String methodName = jp.getSignature().getName();
        System.out.println("【返回通知】the method 【" + methodName + "】 ends with 【" + result + "】");
    }

    /**
     * 异常通知,方法出现异常的时候执行
     * @param jp
     * @param e
     */
    @AfterThrowing(value = " execution(* com.zzq.controller.*.*(..)) " , throwing = "e")
    public void afterReturning(JoinPoint jp , Throwable e){
        String methodName = jp.getSignature().getName();
        System.out.println("【异常通知】the method 【" + methodName + "】 has exception 【" + e.getMessage() + "】");
    }

}

3.通知类注入(配置)

上面的类写完之后,还不会生效,因为没注入。

此处注入需要  @EnableAspectJAutoProxy 注解

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@EnableAspectJAutoProxy
@Configuration
public class AspectConfig {

    @Bean
    public ControllerAspect controllerAspect(){
        return new ControllerAspect();
    }

}

4.效果

正常执行:

SpringBoot 基于 @Aspect 的aop实现_第1张图片

执行失败:

SpringBoot 基于 @Aspect 的aop实现_第2张图片

5.心得

通知自己的实践发现了 几个问题,不知道结论是否正确,如有不正确还望各位大佬提出。

1.在 切面方法 里面 执行 其他的被代理的方法的时候 aop 是不生效的。

比如说我控制器里面有两个方法,在一个控制器里面调用另外一个控制器的方法,通知是不生效的。

如图:

SpringBoot 基于 @Aspect 的aop实现_第3张图片

2.异常通知,如果异常不是发生在该类,是发生在被调用方法里面,并且没有抛出异常,而是直接内部处理,这个  异常通知  是不会统治的。其实方法都没有抛异常,不通知应该也很正常。

你可能感兴趣的:(springboot,aop,SpringBoot菜鸟教程)