十四Spring Aop以及AspectJ框架的使用二

前面简单的介绍了一下@Before注解的使用,其实AspectJ支持5种类型的通知注解:

@Before: 前置通知, 在方法执行之前执行
@After: 后置通知, 在方法执行之后执行 
@AfterReturning: 返回通知, 在方法返回结果之后执行
@AfterThrowing: 异常通知, 在方法抛出异常之后
@Around: 环绕通知, 围绕着方法执行

下面我们来详细介绍一下下面这四种注解的的使用:

1.后置通知:

后置通知是在连接点完成之后执行的, 即连接点返回结果或者抛出异常的时候, 后置通知中的方法都会执行。

下面写一个后置通知的方法:

/**后置通知
     * 在后置通知中还不能访问目标
     * 方法执行的 结果
     * */
    @After("execution(* com.spring.aop.*.*(int,int))")
    public void afterMethod(JoinPoint joinPoint){
        String methodname=joinPoint.getSignature().getName();

        System.out.println("The method "+methodname+" ends");
    }
具体的配置可以参考前面一篇博文,这里不再赘述。

在主程序中制造一个异常:

public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        AtitheticCalculator atitheticCalculator=ctx.getBean(AtitheticCalculator.class);
        int result=atitheticCalculator.div(3,0);
        System.out.println(result);

    }
}

十四Spring Aop以及AspectJ框架的使用二_第1张图片

后置通知还是得到了运行。

2.返回通知:

/**
     * 在方法结束后
     * 受执行的代码
     * 返回通知是可以访问到方法的返回值的
     * */
    @AfterReturning(value="execution(public int com.spring.aop.AtitheticCalculator.*(..))",returning = "result")
    public void afterReturing(JoinPoint joinPoint,Object result){
        String methodName=joinPoint.getSignature().getName();
        System.out.println("The method "+methodName+" ends with "+result);
    }
public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        AtitheticCalculator atitheticCalculator=ctx.getBean(AtitheticCalculator.class);
        int result=atitheticCalculator.div(9,3);
        System.out.println(result);

    }
}
执行之


3.异常通知

/**
     * 异常通知
     * 在方法出现异常时会执行的代码
     * 而且可以访问到异常对象
     * 且可以指定出现特定异常是再执行特定的代码
     * */
    @AfterThrowing(value="execution(public int com.spring.aop.AtitheticCalculator.*(..))",throwing = "ex")
    public void afterThrowing(JoinPoint joinPoint,Exception ex){
        String methodName=joinPoint.getSignature().getName();
        System.out.println("The method "+methodName+" occurs exception:"+ex);
    }

public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        AtitheticCalculator atitheticCalculator=ctx.getBean(AtitheticCalculator.class);
        int result=atitheticCalculator.div(9,0);
        System.out.println(result);

    }
}

十四Spring Aop以及AspectJ框架的使用二_第2张图片

4.环绕通知

环绕通知是所有通知类型中功能最为强大的, 能够全面地控制连接点.

甚至可以控制是否执行连接点.对于环绕通知来说, 连接点的参数类型必须是 ProceedingJoinPoint . 它是 JoinPoint 的子接口, 允许控制何时执行, 是否执行连接点.

在环绕通知中需要明确调用 ProceedingJoinPoint 的 proceed() 方法来执行被代理的方法. 如果忘记这样做就会导致通知被执行了, 但目标方法没有被执行.

注意: 环绕通知的方法需要返回目标方法执行之后的结果, 即调用 joinPoint.proceed(); 的返回值, 否则会出现空指针异常 。

ex:

/**
     *
     *环绕通知需要携带ProceedingJoinPoint类型的参数
     *
     *环绕通知类似于动态代理的全过程:ProceedingJoinPint 类型的参数可以决定是否执行目标方法
     * 且环绕通知必须要有返回值,返回值必为目标方法的返回值
     */


    @Around("execution(public int com.spring.aop.AtitheticCalculator.*(..))")
    public Object aroundMethod(ProceedingJoinPoint pjd){
        Object result=null;
        String methodName=pjd.getSignature().getName();
        try {
            //前置
            System.out.println("The method "+methodName+" begin with "+Arrays.asList(pjd.getArgs()));
            //执行目标方法
            result=pjd.proceed();
            //返回
            System.out.println("The method "+methodName+" ends whith "+result);
        } catch (Throwable throwable) {

            //异常通知
            System.out.println("The method occors exception:" +throwable);
            throw new RuntimeException(throwable);//为了防止返回值result为null的情况
        }
        //后置
        System.out.println("The method "+methodName+" ends");
        return result;
    }

public class Main {
    public static void main(String[] args) {
        ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
        AtitheticCalculator atitheticCalculator=ctx.getBean(AtitheticCalculator.class);
        int result=atitheticCalculator.div(9,0);
        System.out.println(result);

    }
}

十四Spring Aop以及AspectJ框架的使用二_第3张图片


最后讲一下切面的优先级:

在同一个连接点上应用不止一个切面时, 除非明确指定, 否则它们的优先级是不确定的.切面的优先级可以通过实现 Ordered 接口或利用 @Order 注解指定.实现 Ordered 接口, getOrder() 方法的返回值越小, 优先级越高.若使用 @Order 注解, 序号出现在注解中

ex:

十四Spring Aop以及AspectJ框架的使用二_第4张图片

那么上一个切面会先得到执行,后面一个切面会在后面执行。

你可能感兴趣的:(spring,spring,aop)