Spring AOP 怎么用才正确,你更喜欢哪种用法

Spring AOP(Aspect-Oriented Programming,面向切面编程),简单地说就是将那些与业务无关,却为业务模块所共同调用的逻辑或业务封装起来,再把封装功能整合到业务中。好处:便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性

使用@Aspect注解

@Component
@Aspect
public class LogAspect {
    @Pointcut("execution(* com.example.demo.Aspect.TestController.doNormal(..))")
    public void pointCut(){}

    @Before(value = "pointCut()")
    public void before(JoinPoint joinPoint){
        System.out.println("before通知执行结束");
    }

    /**
     * 	后置返回
     *  如果第一个参数为JoinPoint,则第二个参数为返回值的信息
     *  如果第一个参数不为JoinPoint,则第一个参数为returning中对应的参数
     *  returning:只有目标方法返回值与通知方法参数类型匹配时才能执行后置返回通知,否则不执行,
     *  参数为Object类型将匹配任何目标返回值
     */
    @AfterReturning(value = "pointCut()",returning = "result")
    public void doAfterReturningAdvice1(JoinPoint joinPoint,Object result){
       System.out.println("第一个后置返回通知的返回值:"+result);
    }

    @AfterReturning(value = "pointCut()",returning = "result",argNames = "result")
    public void doAfterReturningAdvice2(String result){
        System.out.println("第二个后置返回通知的返回值:"+result);
    }
   
    /**
     *  后置异常通知
     *  定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;
     *  throwing:只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行异常通知,否则不执行,
     *  对于throwing对应的通知方法参数为Throwable类型将匹配任何异常。
     */
    @AfterThrowing(value = "pointCut()",throwing = "exception")
    public void doAfterThrowingAdvice(JoinPoint joinPoint,Throwable exception){
        System.out.println(joinPoint.getSignature().getName());
        if(exception instanceof NullPointerException){
           System.out.println("发生了空指针异常!!!!!");
        }
    }
    
    @After(value = "pointCut()")
    public void doAfterAdvice(JoinPoint joinPoint){
        System.out.println("后置通知执行了!");
    }

    /**
     *   环绕通知:
     *   注意:Spring AOP的环绕通知会影响到AfterThrowing通知的运行,不要同时使用
     *   环绕通知非常强大,可以决定目标方法是否执行,什么时候执行,执行时是否需要替换方法参数,执行完毕是否需要替换返回值。
     *   环绕通知第一个参数必须是org.aspectj.lang.ProceedingJoinPoint类型
     */
    @Around(value = "pointCut()")
    public Object doAroundAdvice(ProceedingJoinPoint proceedingJoinPoint){
        System.out.println("@Around环绕通知:"+proceedingJoinPoint.getSignature().toString());
        Object obj = null;
        try {
            obj = proceedingJoinPoint.proceed(); //可以加参数
            System.out.println(obj.toString());
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
       System.out.println("@Around环绕通知执行结束");
        return obj;
    }
}

使用代码配置

第一种:实现MethodInterceptor接口

public class MyInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("方法执行前");
        Object obj = methodInvocation.proceed();
        System.out.println("方法执行后");
        return obj;
    }
}
@Configuration
public class MyConfiguration {
    // 切注解
    // public static final String traceExecution = "@annotation(com.v5ba.common.Encrypt)";
    // 切方法
    public static final String traceExecution = "execution(* com.example.methodinterceptor..*.*(..))";
    
    @Bean
    public DefaultPointcutAdvisor defaultPointcutAdvisor2() {
        MyInterceptor interceptor = new MyInterceptor();
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(traceExecution);

        // 配置增强类advisor
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        advisor.setPointcut(pointcut);
        advisor.setAdvice(interceptor);
        return advisor;
    }
}

第二种:实现MethodBeforeAdvice, AfterReturningAdvice接口

public class MyAdvice implements MethodBeforeAdvice, AfterReturningAdvice {

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("Aop after");
    }

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("Aop before");
    }
}
@Configuration
public class MyConfiguration {
		// 切注解
    // public static final String traceExecution = "@annotation(com.v5ba.common.Encrypt)";
    // 切方法
    public static final String traceExecution = "execution(* com.example.methodinterceptor..*.*(..))";
    
    @Bean
    public DefaultPointcutAdvisor defaultPointcutAdvisor() {
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor();
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(traceExecution);
        advisor.setPointcut(pointcut);
        advisor.setAdvice(new MyAdvice());
        return advisor;
    }
}
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章