Spring中的aop有两种配置方式,分别是注解类型的配置和xml类型的配置。通常来说注解的配置优于xml的配置,但是当你无法获取类的源码时就没办法在类上使用注解的配置了,此时xml配置方式正好弥补了这一缺陷。今天我们来看一下如何通过xml配置Spring的AOP。
第一步:编写切面类
切面包含了切点和通知,其中切点决定了在哪里执行,通知决定了什么时候、执行什么内容。切面首先是一个普通的java类,通知的行为就是类的方法。如下图我们编写了一个切面类:
这个时候这些方法也仅仅是一些普通的类方法,可以通过MyAspect类的实例正常的调用,这再普通不过了。那么如何才能让他们成为通知呢?后面我们会讲到。不过我们开始之前首先需要对这个类的这些方法的定义和实现说明一下。
异常通知方法throwAdvice()的参数
这个参数用于接收抛出的异常
环绕通知方法aroundAdvice()的参数
ProceedingJoinPoint参数用于控制目标方法是否执行。因为这是一个around类型的通知,需要手动控制是否执行目标方法
打印堆栈信息
大家应该都留意到了这条语句:

这条语句是打印堆栈信息的,其中通过Thread.currentThread()获取当前线程,然后通过getStackTrace()获取当前的堆栈信息,这个方法返回的是一个数组,我们取坐标为1的栈帧,即可得到执行这条语句的方法是哪一个了,用于调试程序很方便。打印结果如下:
com.example.aspect.MyAspect.beforeAdvice(MyAspect.java:9)
因为我们在这个方法里调用了上图的方法,所以会打印出来调用者。
第二步:把切面类设置为一个Spring管理的bean
切面首先是一个bean,这一点大家要清楚。至于如何把这个切面设置成Spring中的bean,XML配置、java配置和扫描配置都是可以的。如下图所示我们通过最常用的扫描方式把这个切面类设置成为一个bean。
开启扫描,这里我们在base-package里面通过英文逗号设置了2个包。

使用注解标记bean:
第三步:在xml中配置切面
到目前为止,我们已经编写了切面类并且把它设置成了一个Spring的bean。不过这是这个切面类MyAspect还不能被Spring作为一个切面来对待,这时它还只是一个普通的bean。那么还需要做什么才能把它作为一个真正的切面bean呢?其实也很简单。只需要在<aop:config>标签的ref属性上进行一下引用就可以把MyAspect这个类作为一个真正的切面类,如下:

第四步:在xml中配置切点
在xml中配置的aop元素都是在<aop:config>标签内进行配置的。
在xml中配置切点是由<aop:pointcut>标签来完成的,<aop:pointcut>标签可以在以下2个位置配置
1. 在<aop:config>标签内。
2.在<aop:aspect>标签内。
切点中有一个id属性,用于为切点设置一个唯一标识,以便于引用。expression属性用于指定切点的表达式。如下:
<aop:pointcut id="afterPt" expression="execution(* com.example.service..*.afterMd(..))"/>
第五步:在xml中配置通知
通知需要配置在切面标签<aop:aspect>里面,下面列出了配置通知的标签和其含义:
<aop:before>:前置通知,目标方法执行前会执行
<aop:after>:后置通知,目标方法正常结束或异常结束后会执行
<aop:after-returning>:返回通知,当目标方法正常return后执行的通知
<aop:after-throwing>:异常通知,目标方法抛出异常后会执行
<aop:around>:环绕通知,可以通过ProceedingJoinPoint参数手动控制是否执行目标方法
在配置通知时,method属性用于指定通知方法,pointcut属性用于直接填写切点,pointcut-ref属性用于引用现存的切点,pointcut和pointcut-ref选择其一就可以了,如图:

通过以上5步之后整个过程就结束了。下面我们来看一下一个完整的xml配置:

下面解答2个疑问点,分别是通知如何接收异常和目标方法的参数:
通知如何接收异常?
1.建议通过切点匹配具体的异常类型
在配置切点表达式时可以通过throws来指定具体的异常类型,当然这并不是必须的。图中就指定了一个NullPointerException异常,只有当目标方法抛出的异常类型和切点配置的异常类型匹配时,对应的通知才会执行。

2.异常参数名称必须一样
在配置异常通知时通过<aop:after-throwing>标签的throwing属性来指定传入通知方法的参数名称,这个名称要和通知方法的名称一样才可以,如下图的名称都为e:


3.通知方法的异常类型和抛出的异常类型必须要匹配
异常通知的方法的参数类型也要能够匹配到抛出的异常才可以,即通知的异常类型需要和抛出的异常类型保持一致或者是其父类。如图我们抛出了一个NullPointerException异常,通知方法指定了一个Exception,这是可以的,因为Exception是NullPointerException的父类。但是当我们的通知的方法的参数是其他不匹配的类型时,则通知不会执行。
通知如何接收参数?
1.建议通过切点精准匹配目标方法的参数类型
在切点中最好是通过具体的类型来指定参数类型,而不是通过“..”来模糊匹配所有的参数,然后通过and操作符和args来指定要匹配的参数,如下图不推荐(..)来模糊匹配:


2.通知方法的参数名要和xml切点中args配置的的参数名一样
切点中我们通过args指定了name和addr两个参数名,这两个参数名要和通知的参数名一样,但是顺序可以不一样。如下图通知的参数名称也是name和addr,和args指定的参数名称一样:

总结
以上我们介绍了xml如何配置Spring的aop。重点介绍了异常通知和如何在通知中接收参数。总体上来说并不是很难,另外对于切点的编写我们会再开一篇文章进行论述,因为关于如何定义切点也会有不少内容。那么今天的内容就到这里啦,小伙伴们有什么疑问可以在评论区留言哦。
网友评论