2018暑期充实日记(2)Spring-AOP

spring aop通知(advice)分成五类: 
前置通知[Before advice] :在连接点前面执行,前置通知不会影响连接点的执行,除非此处抛出异常。 
正常返回通知[After returning advice] :在连接点正常执行完成后执行,如果连接点抛出异常,则不会执行。 
异常返回通知[After throwing advice] :在连接点抛出异常后执行。 
返回通知[After (finally) advice] :在连接点执行完成后执行,不管是正常执行完成,还是抛出异常,都会执行返回通知中的内容。 

环绕通知[Around advice]:环绕通知围绕在连接点前后,比如一个方法调用的前后。这是最强大的通知类型,能在方法调用前后自定义一些操作。环绕通知还需要负责决定是继续处理join point(调用ProceedingJoinPoint的proceed方法)还是中断执行。 

以上是查阅文档时别人文档给出的解释,接下来我们实践一下,最后看看效果的差别。

前置通知和返回通知已经在上一篇看过了,我们这里测试around

 @Around("execution(* com.hjj.source.math.math1.*(..))")
    public double around(ProceedingJoinPoint jp){
        try{
            System.out.println("--------around begin--------");
            jp.proceed();
            System.out.println("---------around end---------");
        }catch(Throwable e){
            e.printStackTrace();
        }
        return 0;
    }

同样,注释Around,使用环绕通知需要注意亮点,1:环绕开始后需要执行一次proceed,不然此方法阻塞,程序无法执行。

2.环绕通知的返回类型,必须与切点的返回类型一致,不然会报错,就像这样

Null return value from advice does not match primitive return type for: public double com.hjj.source.math.math1.add(double,double)

我这里修改around的返回类型为double,在实际过程中这一点需要考虑到。

--------around begin--------
----------运算开始----------
add
12.34+23.45=35.79
---------around end---------
----------运算结束----------

这里可以看到执行的顺序为around-before-around-after。至于其他两个是针对程序运行的正常与否进行检查的。

这里上代码

 @AfterReturning("execution(* com.hjj.source.math.math1.*(..))")
    public void aftereturing(JoinPoint jp){
        System.out.println("----------正常----------");
    }

    @AfterThrowing(throwing = "ex",pointcut = "execution(* com.hjj.source.math.math1.*(..))")
    public void afterthrowing(Throwable ex){
        System.out.println("----------异常----------");
        System.out.println(ex);
    }
接下来,改写一下源代码,抛出一个zero异常
//除
    public double div(double n1,double n2){
        double result=n1/n2;
        System.out.println(n1+"/"+n2+"="+result);
        if (n2==0) throw new IllegalArgumentException("除数不能为0");
        return result;
    }
然后看一下结果,了解了afterruning和afterthrowing的区别。(只会执行其中一个,而且一定会执行一个,多数用在日志记录里)。

----------运算开始----------
mut
12.34X0.0=0.0
----------运算结束----------
----------正常----------
----------运算开始----------
div
12.34/0.0=Infinity
----------运算结束----------
----------异常----------
java.lang.IllegalArgumentException: 除数不能为0

因为能力有限,只了解了Spring中AOP的部分,利用Aspectj进行注解进行配置,而AspectJ还有许多强大的功能和复杂的语法,这里就不深入了解了,最后了解一下,切入点的多种表达形式,在实际运用过程中可以再深入学习一下,这里先mark。

Spring AOP支持的切入点指示符:

(1)execution:用来匹配执行方法的连接点

A:@Pointcut("execution(* com.aijava.springcode.service..*.*(..))")

第一个*表示匹配任意的方法返回值,..(两个点)表示零个或多个,上面的第一个..表示service包及其子包,第二个*表示所有类,第三个*表示所有方法,第二个..表示

方法的任意参数个数

B:@Pointcut("within(com.aijava.springcode.service.*)")

within限定匹配方法的连接点,上面的就是表示匹配service包下的任意连接点

C:@Pointcut("this(com.aijava.springcode.service.UserService)")

this用来限定AOP代理必须是指定类型的实例,如上,指定了一个特定的实例,就是UserService

D:@Pointcut("bean(userService)")

bean也是非常常用的,bean可以指定IOC容器中的bean的名称


猜你喜欢

转载自blog.csdn.net/weixin_40553838/article/details/80747730