7 基于XML配置的Spring AOP
基于XML配置的Spring AOP需要引入AOP配置的Schema,然后我们就可以使用AOP Schema下定义的config、aspect、pointcut等标签进行Spring AOP配置了。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">
</beans>
基于XML配置的Spring AOP的核心配置是config元素,其它的诸如切面配置、切入点配置等都是配置在它的下面的,所以我们需要先定义一个config元素。
7.1 配置切面
切面的配置是通过aspect元素配置的,我们需要通过其ref属性指定切面类对应的Spring bean的id或name,还可以通过其order属性指定切面类的在拦截的时候的优先级。需要说明的是在使用Spring时基于XML的配置和基于注解的配置往往是可以混用的,所以在下面示例中我们使用的切面类引用不一定非得在Spring的bean配置文件中进行配置。
<bean id="schemaBasedAspect" class="com.elim.spring.aop.aspect.SchemaBasedAspect"/>
<!-- 基于XML的AOP配置是基于config元素开始的 -->
<aop:config>
<!-- 定义切面 -->
<aop:aspect id="aspect1" ref="schemaBasedAspect" order="1">
</aop:aspect>
</aop:config>
7.2 配置切入点
切入点可以是直接配置在config元素下的,意为顶级切入点,也可以是配置在指定的aspect下面的。切入点的配置是通过pointcut元素来配置的,在配置的时候我们需要指定id和expression属性,expression属性就对应的是切入点的表达式,其配置规则跟基于Aspectj注解配置时的规则是一样的。如下示例中就定义了两个pointcut,一个是顶级的,一个是在aspectj1中定义的。需要注意的是顶级的Pointcut必须定义在aspect之前。
<aop:config>
<aop:pointcut expression="bean(userService)" id="userServicePointCut2"/>
<!-- 定义切面 -->
<aop:aspect id="aspect1" ref="schemaBasedAspect" order="1">
<aop:pointcut expression="bean(userService)" id="userServicePointCut"/>
</aop:aspect>
</aop:config>
如果我们的切入点是以Aspectj注解的形式定义在类里面的,我们也可以像在前面介绍的基于Aspectj注解配置那样进行引用,如在下面这个配置就是使用的在SchemaBasedAspect类的pointcut方法上通过@Pointcut指定的表达式。
<aop:pointcut expression="com.elim.spring.aop.aspect.SchemaBasedAspect.pointcut()" id="pointcut"/>
7.3 配置Advice
切面的最终目的是为了拦截指定切入点的方法执行,然后加入自己特定逻辑的,有了切面定义和切入点的定义后,我们需要定义在哪些切入点上需要使用切面的哪些Advice,即执行切面类的哪些方法。我们知道Advice有before、after、after returning、after throwing和around五种,对应的分别是before、after、after-returning、after-throwing和around标签,它们都是定义在aspect标签下的。这五类Advice在定义时的用法基本上是类似的,通过method方法指定Advice对应的是aspect类的哪个方法,然后通过pointcut指定切入点的表达式,或者通过pointcut-ref指定需要引用的是哪个切入点。如下示例中我们就定义了两个Advice,before Advice指定了对应的是切面类的doBefore方法,然后通过pointcut-ref指定需要使用的切入点是id为userServicePointCut的切入点;around Advice指定了对应的是切面类的doAround方法,然后通过pointcut直接指定了需要作用的切入点表达式。
<aop:aspect id="aspect1" ref="schemaBasedAspect" order="1">
<!-- 定义一个Around Advice -->
<aop:before method="doBefore" pointcut-ref="userServicePointCut" />
<aop:around method="doAround" pointcut="bean(userService)"/>
<aop:pointcut expression="bean(userService)" id="userServicePointCut"/>
</aop:aspect>
和基于注解的配置类似,如果我们需要在afterReturning Advice中访问返回值,我们也可以给对应的处理方法一个返回值对应类型(或Object类型)的参数,然后通过after-returning元素的returning属性指定返回值需要赋予给Advice处理方法的哪个参数,参数名需要一致。同样afterThrowing类型的Advice需要在处理方法中接收抛出的异常时,也可以给定对应的处理方法一个Exception类型的参数,然后通过after-throwing元素的throwing属性指定抛出的异常需要赋值给Advice处理方法的哪个参数。
<aop:after-returning method="doAfterReturning" pointcut-ref="pointcut" returning="returnValue"/>
<aop:after-throwing method="doAfterThrowing" pointcut-ref="pointcut" throwing="ex"/>
参数传递也是类似的,在Advice处理方法上给定指定的参数,然后在定义Pointcut表达式的时候加上对应的参数传递限制,如“args(id)”、“this(userService)”等,在需要指定参数的绑定顺序时,可以通过before、around等Advice标签的arg-names属性指定。如下示例中我们就要求id为userServicePointCut的Pointcut需要接收一个参数,这个参数是需要跟对应的Advice处理方法绑定的,而before Advice是使用该Pointcut的,所以就要求id与对应的处理方法参数绑定,而且对应的方法参数名需要是id。
<aop:aspect id="aspect1" ref="schemaBasedAspect" order="1">
<aop:before method="doBefore" pointcut-ref="userServicePointCut"/>
<aop:around method="doAround" pointcut="bean(userService)" />
<aop:pointcut expression="bean(userService) && args(id)" id="userServicePointCut"/>
</aop:aspect>
我们对应的doBefore处理方法是这样的。
public void doBefore(int id) {
System.out.println("======================doBefore======================" + id);
}
在上面的示例中在定义id为userServicePointcut的表达式的时候用到了“&&”,这是因为在XML中&是特殊字符,我们必须对它进行转义。其实在XML中配置Pointcut表达式时我们可以使用“and”、“or”和“not”替代“&&”、“||”和“!”。
7.4 declare-parents
在基于注解的形式定义AOP时,我们有一个@DeclareParents注解可以给所有匹配的bean生成的代理默认加上指定的接口实现,并使用默认的实现。如果是基于XML配置时如果想达到对应的效果我们可以通过declare-parents元素来达到对应的效果。示例如下,切面类SchemaBasedAspect有一个doBefore方法接收一个CommonParent参数,我们在配置切面时配置了一个before Advice将调用切面类的doBefore方法;通过declare-parents元素指定service包下面所有的类都实现CommonParent接口,底层在调用的时候将会调用CommonParentImpl的实现。CommonParent接口的源码没有提供,其只定义了一个返回类型为void的doSomething()方法。然后我们的before Advice将拦截id为userService的bean的所有方法调用,注意因为我们声明了所有的Service都将实现CommonParent接口,所以生成的id为userService的bean其实也是实现了CommonParent接口的,在调用的doBefore方法时传递的就是id为userService的bean,我们在doBefore方法中又继续调用CommonParent的doSomething方法就相当于重新调用了id为userService的bean的方法,会造成before Advice循环拦截和调用。很显然此种情况下,我们是不希望CommonParent的方法调用还被拦截的,所以我们在对应的Pointcut表达式上把CommonParent的doSomething方法排除了。在应用注解的时候不用排除也不会循环调用,但是使用XML配置时必须排除。
public void doBefore(CommonParent commonParent) {
System.out.println("======================doBefore======================");
commonParent.doSomething();
}
<bean id="schemaBasedAspect" class="com.elim.spring.aop.aspect.SchemaBasedAspect" />
<bean id="commonParent" class="com.elim.spring.aop.service.CommonParentImpl" />
<!-- 基于XML的AOP配置是基于config元素开始的 -->
<aop:config>
<aop:aspect id="aspect1" ref="schemaBasedAspect" order="1">
<aop:before method="doBefore" pointcut-ref="userServicePointCut" />
<aop:pointcut expression="bean(userService) and this(commonParent) and !execution(void com.elim.spring.aop.service.CommonParent.doSomething())"
id="userServicePointCut" />
<!-- 加上通用的父类 -->
<aop:declare-parents types-matching="com.elim.spring.aop.service..*"
implement-interface="com.elim.spring.aop.service.CommonParent"
delegate-ref="commonParent"/>
</aop:aspect>
</aop:config>
7.5 启用CGLIB代理类
默认情况下当bean实现了接口时Spring AOP是基于JDK的动态代理的,也就是说我们生成的bean只能调用接口中定义的方法,如果我们的bean是没有实现接口的,则会采用CGLIB代理。如果我们希望不管bean是否实现了接口都采用CGLIB代理,则在基于Aspectj注解进行AOP配置时,我们可以通过aspectj-autoproxy元素的proxy-target-class=”true”启用CGLIB代理。
<aop:aspectj-autoproxy proxy-target-class="true" />
如果是基于XML的配置时,我们也希望强制使用CGLIB代理时怎么办呢?我们可以在config元素上配置proxy-target-class=”true”。
<aop:config proxy-target-class="true">
</aop:config>
(注:本文是基于Spring4.1.0所写,Elim写于2017年1月23日星期一)
相关推荐
下面将详细介绍Spring AOP的注解方式和XML配置方式。 ### 注解方式 #### 1. 定义切面(Aspect) 在Spring AOP中,切面是包含多个通知(advisors)的类。使用`@Aspect`注解标记切面类,例如: ```java @Aspect ...
XML配置是Spring AOP早期的主要实现方式,虽然现在有更简洁的注解式配置,但理解XML配置方式对于深入理解AOP原理仍然很有帮助。下面我们将详细探讨如何通过XML配置实现Spring AOP。 首先,我们需要在Spring配置文件...
这篇博客“Spring AOP + AspectJ in XML配置示例”旨在指导开发者如何在XML配置中实现Spring AOP和AspectJ的结合。 首先,我们需要理解AOP的基本概念。AOP通过将关注点(如日志、事务管理)与业务逻辑分离,提高了...
在基于XML的配置方式下,我们将通过这些概念来理解Spring 2.0的AOP实现。 1. **切面(Aspect)**:一个关注点的模块化,例如日志记录、事务管理等。在Spring中,切面可以由一个或多个通知以及定义它们何时何地触发...
在基于XML的配置方式下,Spring AOP提供了直观且灵活的声明式方法来实现这些关注点的分离,使得业务逻辑代码更为简洁。 在Spring AOP中,我们首先需要定义一个切面(Aspect),它包含了若干个通知(Advice)。通知...
**Spring AOP XML方式配置通知** 在Java世界中,Spring框架是广泛应用的IoC(Inversion of Control)和AOP(Aspect Oriented Programming)容器。AOP允许开发者定义“方面”,这些方面可以封装关注点,如日志、事务...
本文将深入探讨“Spring AOP——Schema”,这是Spring AOP的一种配置方式,通过XML schema定义切面和通知。 首先,我们需要理解AOP的基本概念。面向切面编程是一种编程范式,旨在提高软件的模块化程度,将关注点...
在使用Spring AOP时,我们可以通过XML配置或注解的方式来定义切面。例如,可以使用`@Aspect`注解定义一个切面类,`@Before`、`@After`等注解来声明通知,`@Pointcut`定义切点表达式。 在实际开发中,Spring AOP广泛...
通过这个入门案例,你可以逐步学习如何创建和配置切面,以及如何利用Spring AOP实现实际的需求。在实践中,你会看到如何利用AOP提升代码的可维护性和可复用性,避免了横切关注点对业务代码的侵入。同时,它也会帮助...
然而,随着Spring的发展,基于注解的AOP配置逐渐成为主流,因为它的简洁性和可读性更强。但这并不意味着XML配置方式失去了价值,尤其是在需要更细粒度控制或者与旧项目集成时,XML配置依然有着其独特的优势。 总的...
本篇文章主要讲解如何通过XML配置来实现Spring AOP的开发。 首先,了解AOP的基本概念。AOP通过“切面”(Aspect)来封装横切关注点,切面由“通知”(Advice)和“连接点”(Join Point)组成。通知是在特定连接点...
Spring AOP主要通过两种方式实现:XML配置和注解。本实例主要探讨的是使用XML配置的方式来实现AOP。XML配置虽然相比注解方式略显繁琐,但它提供了更大的灵活性,尤其是在需要对多个类或方法应用相同通知(Advice)时...
**Spring AOP:基于Schema配置的总结与案例** 在Java企业级开发中,Spring框架以其强大的功能和灵活性深受开发者喜爱。其中,Spring AOP(面向切面编程)是解决横切关注点问题的一个重要工具,它允许我们把业务逻辑...
**Spring AOP XML配置**是Spring框架中一种重要的面向切面编程(Aspect-Oriented Programming,简称AOP)实现方式,允许开发者定义“横切关注点”,如日志、事务管理等,这些关注点可以独立于业务代码进行,提高代码...
Spring AOP通过XML配置文件提供了灵活的方式来定义和管理切面、切入点和通知,使得我们可以轻松地在应用程序中实现横切关注点的解耦。了解和掌握Spring AOP的配置实现,有助于提升我们构建松散耦合、易于维护的系统...
Spring支持两种AOP的实现方式:Spring AspectJ注解风格和Spring XML配置风格。使用AspectJ注解风格是最常见的,它允许开发者直接在方法上使用注解来定义切面。 Spring AOP中有五种不同类型的的通知(Advice): 1....
在"Spring AOP管理XML版"中,我们主要关注的是通过XML配置来管理AOP。以下是一些关键的XML配置元素: - `<aop:config>`:这是AOP配置的根元素,包含所有其他的AOP配置。 - `<aop:aspect>`:定义一个切面,内部可以...
本教程将探讨如何在Spring中结合AspectJ实现AOP,包括基于XML配置和基于注解的方式。 **一、AOP基本概念** AOP的核心概念有切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)和引入...
Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种模块化和声明式的方式来处理系统中的交叉关注点问题,如日志、事务管理、安全性等。本示例将简要介绍如何在Spring应用中实现AOP,通过实际的...
现在,我们回到主题——"springaop依赖的jar包"。在Spring 2.5.6版本中,使用Spring AOP通常需要以下核心jar包: - `spring-aop.jar`:这是Spring AOP的核心库,包含了AOP相关的类和接口。 - `spring-beans.jar`:...