Spring中的AOP(七)——基于XML配置文件方式的AOP

简介:

    除了前面介绍的基于JDK1.5的注解方式来定义切面,切入点和增强处理外,Spring AOP也允许直接使用XML配置文件来管理它们。在JDK1.5之前,只能使用配置文件的方式来管理,在Spring2.X后提供了一个新的aop命名空间来定义切面、切入点和增强处理。

    相比之下,使用XML配置文件方式有如下优点:

  • 如果没有使用JDK1.5以上版本,只能使用XML配置文件的方式

  • 对早期的Spring用于来说更加习惯,而且这种方式允许使用纯粹的POJO来支持AOP

  • 采用XML配置方式时,我们可以清晰的看到系统中存在哪些切面

    同时,XML配置文件的方式也有如下缺点:

  • 不能将切面,切入点和增强处理等封装到一个地方。当我们需要查看切面、切点和增强处理时,必须同时结合Java文件和XML配置文件

  • XML配置文件方式比@AspectJ方式有更多限制:仅支持“singleton”切面Bean,不能在XML中组合多个命名连接点的声明

    除此之外,@AspectJ切面还有一个优点就是能被Spring AOP和AspectJ同时支持,如果有一天我们需要将应用改为AspectJ来实现AOP,使用@AspectJ将非常容易迁移。

    在Spring的配置文件中,所有的切面、切点和增强处理都必须定义在<aop:config../>元素内部。<beans../>元素可以包含多个<aop:config../>元素,一个<aop:config../>可以包含pointcut、advisor和aspect元素,且这三个元素需要按照此顺序来定义。

    注意:当我们使用<aop:config../>方式进行配置时,可能与Spring的自动代理方式相互冲突,因此,建议要么全部使用<aop:config../>配置方式,要么全部使用自动代理方式,不要把两者混合使用。


配置切面

    配置<aop:config../>元素时,实质是将已有的Spring Bean转换成切面Bean,所以需要先定义一个普通的Spring Bean。因为切面Bean可以当成一个普通的Spring Bean来配置,所以我们完全可以为该切面Bean配置依赖注入。当切面Bean的定义完成后,通过<aop:congig../>元素中是哟个ref属性来引用该Bean,就可以将该Bean转换成切面Bean了。配置<aop:config../>元素时可以指定如下三个属性:

  • id:该切面Bean的标识名

  • ref:指定将要被转换成切面Bean的的普通Bean的id

  • order:指定该切面Bean的优先级,值越小,优先级越高

    如下配置片段定义了一个切面:

?
1
2
3
4
5
6
7
8
<!-- 定义普通的Bean实例 -->
< bean  id = "afterAdviceBean"  class = "com.abc.advice.AfterAdviceBean"  />
< aop:config >
     <!-- 将容器中的afterAdviceBean转换成切面Bean -->
     < aop:aspect  id = "afterAdviceAspect"  ref = "afterAdviceBean" >
         ...
     </ aop:aspect >
</ aop:config >

    上面的配置中,将一个AfterAdviceBean类型普通的Bean对象afterAdviceBean转换成了切面Bean对象afterAdviceAspect。


配置增强处理

    与使用@AspectJ完全一样,使用XML一样可以配置Before、After、AfterReturning、AfterThrowing和Around 5种增强处理,而且完全支持和@Aspect完全一样的语义。使用XML配置增强处理分别依赖于如下几个元素:

  • <aop:before../>:配置Before增强处理

  • <aop:after../>:配置After增强处理

  • <aop:after-returning../>:配置AfterReturning增强处理

  • <aop:after-throwing../>:配置AfterThrowing增强处理

  • <aop:around../>:配置Around增强处理

    这些元素都不支持使用子元素,但通常可以指定如下属性:

  • pointcut:指定一个切入点表达式,Spring将在匹配该表达式的连接点织入增强处理

  • pointcut-ref:指定一个已经存在的切入点名称,通常pointcut和pointcut-ref只需使用其中之一

  • method:指定一个方法名,指定切面Bean的该方法作为增强处理

  • throwing:只对<aop:after-throwing../>元素有效,用于指定一个形参名,AfterThrowing增强处理方法,可通过该形参访问目标方法所抛出的异常

  • returning:只对<aop:after-returning../>元素有效,用于指定一个形参名,AfterThrowing增强处理方法,可通过该形参访问目标方法的返回值

    既然选择XML配置文件的方式来管理切面、切点和增强处理,那么切面类里定义切面,切点和增强处理的注解就可以全部删除了。

    定义切点时,XML配置方式和@AspectJ注解方式支持完全相同的切点指示符,一样可以支持execution、within、args、this、target和bean等切点提示符。另外,XML配置文件方式也和@AspectJ方式一样支持组合切入点表达式,但XML配置方式不再使用简单的&&、|| 和 ! 作为组合运算符(因为直接在XML文件中需要使用实体引用来表示他们),而是使用如下三个组合运算符:and(相当于&&)、or(相当于||)和not(相当于!)。 下面是一个使用<aop:congig../>的例子,这是把前面的例子中关于切面切点和增强处理的注解去掉后,使用XML配置文件来重新实现这些切面切点的功能:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
< bean  id = "adviceTest"  class = "com.abc.advice.AdviceTest"  />
< aop:config >
     <!-- 注意这里可以使用order属性为Aspect指定优先级 -->
     < aop:aspect  id = "firstAspect"  ref = "adviceTest"  order = "2" >
     
         <!-- @Before切点 -->
         < aop:before  pointcut = "execution(* com.abc.service.*.*(..))" 
                 method = "permissionCheck" />
                 
         <!-- @After切点 -->
         < aop:after  pointcut = "execution(* com.abc.service.*.*(..))" 
                 method = "releaseResource" />
                 
         <!-- @AfterReturning切点 -->
         < aop:after-returning  pointcut = "execution(* com.abc.service.*.*(..))" 
                 method = "log" />
                 
         <!-- @AfterThrowing切点 -->
         < aop:after-throwing  pointcut = "execution(* com.abc.service.*.*(..))" 
                 method = "handleException" />
                 
         <!-- @Around切点(多个切点提示符使用and、or或者not连接) -->
         < aop:around  pointcut = "execution(* com.abc.service.*.*(..)) and args(name,time,..)" 
                 method = "process" />
     </ aop:aspect >
</ aop:config >

    上面的定义中,特意为firstAspec指定了order=2,表明firstAspect的优先级为2,如果这个XML文件中还有order=1的Aspect,那么这个Aspect将被Spring AOP优先织入。其执行结果,和前面几篇文章中介绍的相同,这里不再给出。


配置切点

    在Spring中通过<aop:pointcut../>元素来定义切点。当把<aop:pointcut../>元素作为<aop:config../>的子元素时,表明该切点可以被多个切面共享;当把<aop:pointcut../>元素作为<aop:aspect../>的子元素时,表明该切点只能在这个切面内使用。配置<aop:pointcut../>时,通常需要配置如下两个属性:

  • id:指定该切点的标识名

  • expression:指定该切点关联的切点表达式

    如下的配置定义了一个简单的切点:

?
1
<aop:pointcut id= "point1"  expression= "execution(* com.abc.service.*.*(..))"  />

    另外,如果程序中已经使用注解的方式定义了切点,在<aop:pointcut../>元素中指定切入点表达式时还有另一种用法,看例子:

?
1
< aop:pointcut  id = "point2"  expression = "com.abc.service.AdviceTest.myPointcut()"  />

    下面的程序中定义了一个AfterThrowing增强处理,包含该增强处理的切面类如下:

?
1
2
3
4
5
6
7
8
9
package  com.abc.advice;
 
public  class  AfterThrowingAdviceTest {
     //定义一个普通方法作为增强处理方法,这个方法名将在XML配置文件中指定
     public  void  doRecoveryAction(Throwable th) {
         System.out.println( "目标方法抛出异常:"  + th);
         System.out.println( "模拟数据库事务恢复" );
     }
}

    与前面的切面类完全类似,该Java类就是一个普通的Java类。下面的配置文件将负责配置该Bean实例,并将该Bean转换成切面Bean:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
< bean  id = "afterThrowingAdviceTest" 
     class = "com.abc.advice.AfterThrowingAdviceTest"  />
< aop:config >
     <!-- 这个切点将可以被多个<aop:aspect../>使用 -->
     < aop:pointcut  id = "myPointcut" 
         expression = "execution(* com.abc.service.*.*(..))"  />
     
     <!-- 这个aspect由上面的Bean afterThrowingAdviceTest转化而来 -->
     < aop:aspect  id = "aspect1"  ref = "afterThrowingAdviceTest" >
         <!-- 定义一个AfterThrowing增强处理,指定切入点以切面Bean中
             的doRecoverryAction作为增强处理方法 -->
         < aop:after-throwing  pointcut-ref = "myPointcut" 
             method = "doRecoveryAction"  throwing = "th"  />
     </ aop:aspect >
</ aop:config >

    上面的<aop:pointcut../>元素定义了一个全局的切点myPointcut,这样其他切面Bean就可以多次复用这个切点了。<aop:after-throwing../>元素中,使用pointcut-ref属性指定了一个已经存在的切点。


目录
相关文章
|
1月前
|
监控 Java 开发者
Spring AOP动态代理
Spring AOP动态代理
43 1
|
1月前
|
Java Spring 容器
Spring的AOP失效场景详解
Spring的AOP失效场景详解
113 0
|
30天前
|
设计模式 Java Maven
Spring Aop 底层责任链思路实现-springaopdi-ceng-ze-ren-lian-si-lu-shi-xian
Spring Aop 底层责任链思路实现-springaopdi-ceng-ze-ren-lian-si-lu-shi-xian
35 1
|
4天前
|
XML Java 数据库连接
Javaweb之Mybatis的XML配置文件的详细解析
Javaweb之Mybatis的XML配置文件的详细解析
13 0
|
14天前
|
Java Shell 测试技术
一次配置,多场景适用:Spring Boot多套配置文件的深度剖析
一次配置,多场景适用:Spring Boot多套配置文件的深度剖析
31 0
一次配置,多场景适用:Spring Boot多套配置文件的深度剖析
|
23天前
|
XML Java Maven
Spring之Aop的注解使用
Spring之Aop的注解使用
|
29天前
|
Java Spring
Spring 如何实现 AOP
Spring 如何实现 AOP
17 0
|
1月前
|
Java 数据库连接 mybatis
Mybatis+mysql动态分页查询数据案例——Mybatis的配置文件(mybatis-config.xml)
Mybatis+mysql动态分页查询数据案例——Mybatis的配置文件(mybatis-config.xml)
20 1
|
1月前
|
网络安全
ssh(Spring+Spring mvc+hibernate)——applicationContext.xml
ssh(Spring+Spring mvc+hibernate)——applicationContext.xml
7 0
|
1月前
|
Java 编译器 程序员
Spring AOP 和 AspectJ 的比较
Spring AOP 和 AspectJ 的比较
37 0