`
liyixing1
  • 浏览: 958979 次
  • 性别: Icon_minigender_1
  • 来自: 江西上饶
社区版块
存档分类
最新评论

spring aop xml风格

阅读更多
Warning

<aop:config>风格的配置使得Spring auto-proxying机制的使用变得很笨重。如果你已经通过 BeanNameAutoProxyCreator或类似的东西显式使用auto-proxying,它可能会导致问题 (例如通知没有被织入)。 推荐的使用模式是仅仅使用<aop:config>风格, 或者仅仅使用AutoProxyCreator风格。

声明一个切面
有了schema的支持,切面就和常规的Java对象一样被定义成application context中的一个bean。   对象的字段和方法提供了状态和行为信息,XML文件则提供了切入点和通知信息。

切面使用<aop:aspect>来声明,backing bean(支持bean)通过 ref 属性来引用:

声明一个切入点
一个命名切入点可以在<aop:config>元素中定义,这样多个切面和通知就可以共享该切入点。
一个描述service层中所有service执行的切入点可以定义如下:
<aop:config>
  <aop:pointcut id="businessService"
        expression="execution(* com.xyz.myapp.service.*.*(..))"/>
</aop:config>

几乎和@AspectJ切面中的一样,使用基于schema定义风格声明的切入点可以收集(collect) 连接点上下文。例如,下面的切入点收集'this'对象作为连接点上下文并传递它给通知:
<aop:config>

  <aop:aspect id="myAspect" ref="aBean">

    <aop:pointcut id="businessService"
          expression="execution(* com.xyz.myapp.service.*.*(..)) &amp;&amp; this(service)"/>
    <aop:before pointcut-ref="businessService" method="monitor"/>
    ...
   
  </aop:aspect>

</aop:config>
通过包含匹配名字的参数,通知被声明来接收收集的连接点上下文:
public void monitor(Object service) {
    ...
}
当需要连接子表达式的时候,'&&'在XML中用起来非常不方便,所以关键字'and', 'or' 和 'not'可以分别用来代替'&&', '||' 和 '!'。例如,上面切入点更好的写法如下:
<aop:config>

  <aop:aspect id="myAspect" ref="aBean">

    <aop:pointcut id="businessService"
          expression="execution(* com.xyz.myapp.service.*.*(..)) and this(service)"/>
    <aop:before pointcut-ref="businessService" method="monitor"/>
    ...
   
  </aop:aspect>

</aop:config>

声明通知
 

和@AspectJ风格一样,基于schema的风格也支持5种通知类型并且两者具有同样的语义。
前置通知
前置通知在匹配方法执行前运行。在<aop:aspect>中使用<aop:before> 元素来声明它。

<aop:aspect id="beforeExample" ref="aBean">

    <aop:before
      pointcut-ref="dataAccessOperation"
      method="doAccessCheck"/>
         
    ...
   
</aop:aspect>

这里dataAccessOperation是一个顶级(<aop:config>)切入点的id。    而要定义内置切入点,需将pointcut-ref属性替换为pointcut属性:

<aop:aspect id="beforeExample" ref="aBean">

    <aop:before
      pointcut="execution(* com.xyz.myapp.dao.*.*(..))"
      method="doAccessCheck"/>
         
    ...
   
</aop:aspect>
正如我们在@AspectJ风格章节中讨论过的,使用命名切入点能够明显的提高代码的可读性。

Method属性标识了提供通知主体的方法(doAccessCheck)。 这个方法必须定义在包含通知的切面元素所引用的bean中。在一个数据访问操作执行之前 (一个方法执行由切入点表达式所匹配的连接点),切面中的"doAccessCheck"会被调用。
后置通知

后置通知在匹配的方法完全执行后运行。和前置通知一样,可以在<aop:aspect> 里面声明它。例如:

<aop:aspect id="afterReturningExample" ref="aBean">

    <aop:after-returning
      pointcut-ref="dataAccessOperation"
      method="doAccessCheck"/>
         
    ...
   
</aop:aspect>

和@AspectJ风格一样,通知主体可以得到返回值。使用returning属性来指定传递返回值的参数名:

<aop:aspect id="afterReturningExample" ref="aBean">

    <aop:after-returning
      pointcut-ref="dataAccessOperation"
      returning="retVal"
      method="doAccessCheck"/>
         
    ...
   
</aop:aspect>

异常通知

异常通知在匹配方法抛出异常退出时执行。在<aop:aspect>中使用 after-throwing元素来声明:

<aop:aspect id="afterThrowingExample" ref="aBean">

    <aop:after-throwing
      pointcut-ref="dataAccessOperation"
      method="doRecoveryActions"/>
         
    ...
   
</aop:aspect>

和@AspectJ风格一样,通知主体可以得到抛出的异常。使用throwing属性来指定传递异常的参数名:

<aop:aspect id="afterThrowingExample" ref="aBean">

    <aop:after-throwing
      pointcut-ref="dataAccessOperation"
      throwing="dataAccessEx"
      method="doRecoveryActions"/>
         
    ...
   
</aop:aspect>

doRecoveryActions方法必须声明一个名字为dataAccessEx的参数。 参数的类型依照@AfterThrowing所描述的方法强制匹配。例如:方法签名可以如下这般声明:

public void doRecoveryActions(DataAccessException dataAccessEx) {...
doAccessCheck方法必须声明一个名字叫 retVal 的参数。 参数的类型依照@AfterReturning所描述的方法强制匹配。例如,方法签名可以这样声明:

public void doAccessCheck(Object retVal) {...


最终通知

最终通知无论如何都会在匹配方法退出后执行。使用after元素来声明它:

<aop:aspect id="afterFinallyExample" ref="aBean">

    <aop:after
      pointcut-ref="dataAccessOperation"
      method="doReleaseLock"/>
         
    ...
   
</aop:aspect>

环绕通知

环绕通知是最后一种通知类型。环绕通知在匹配方法运行期的“周围”执行。 它有机会在目标方法的前面和后面执行,并决定什么时候运行,怎么运行,甚至是否运行。 环绕通知经常在需要在一个方法执行前后共享状态信息,并且是在线程安全的情况下使用 (启动和停止一个计时器就是一个例子)。注意选择能满足你需求的最简单的通知类型; 如果简单的前置通知能做的事情就绝对不要使用环绕通知。

Around通知使用aop:around元素来声明。通知方法的第一个参数的类型必须是 ProceedingJoinPoint类型。在通知的主体中,调用 ProceedingJoinPoint的proceed()方法来执行真正的方法。 proceed方法也可能会被调用并且传入一个Object[]对象 - 该数组将作为方法执行时候的参数。参见Section 6.2.4.5, “环绕通知”中调用具有 Object[]的proceed方法。

<aop:aspect id="aroundExample" ref="aBean">

    <aop:around
      pointcut-ref="businessService"
      method="doBasicProfiling"/>
         
    ...
   
</aop:aspect>

doBasicProfiling通知的实现和@AspectJ中的例子完全一样(当然要去掉注解):

public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
    // start stopwatch
    Object retVal = pjp.proceed();
    // stop stopwatch
    return retVal;
}

通知参数

Schema-based声明风格和@AspectJ一样,支持多种类型的通知:通过通知方法参数名字来匹配切入点参数。 参见Section 6.2.4.6, “通知参数(Advice parameters)”获取详细信息。如果你希望显式指定通知方法的参数名 (而不是依靠先前提及的侦测策略),可以通过通知元素的arg-names属性来实现,它的处理和 在Section 6.2.4.6.3, “确定参数名”中所描述的对通知注解中"argNames"属性的处理方式一样。 示例如下:

<aop:before
  pointcut="com.xyz.lib.Pointcuts.anyPublicMethod() and @annotation(auditable)"
  method="audit"
  arg-names="auditable"/>

arg-names属性接受由逗号分割的参数名列表。

下面是个稍微复杂的基于XSD的例子,它展示了关联了多个强类型参数的环绕通知的使用。

package x.y.service;

public interface FooService {

   Foo getFoo(String fooName, int age);
}

public class DefaultFooService implements FooService {

   public Foo getFoo(String name, int age) {
      return new Foo(name, age);
   }
}

接下来看切面。注意profile(..)方法接受多个强类型参数, 首先连接点在方法调用时执行,这个参数指明profile(..)会被用作 环绕通知:

package x.y;

import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.StopWatch;

public class SimpleProfiler {

   public Object profile(ProceedingJoinPoint call, String name, int age) throws Throwable {
      StopWatch clock = new StopWatch(
            "Profiling for '" + name + "' and '" + age + "'");
      try {
         clock.start(call.toShortString());
         return call.proceed();
      } finally {
         clock.stop();
         System.out.println(clock.prettyPrint());
      }
   }
}

最后这里是使得上面的通知针对一个特定连接点而执行所必需的XML配置:

<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

   <!-- this is the object that will be proxied by Spring's AOP infrastructure -->
   <bean id="fooService" class="x.y.service.DefaultFooService"/>

   <!-- this is the actual advice itself -->
   <bean id="profiler" class="x.y.SimpleProfiler"/>

   <aop:config>
      <aop:aspect ref="profiler">

         <aop:pointcut id="theExecutionOfSomeFooServiceMethod"
                    expression="execution(* x.y.service.FooService.getFoo(String,int))
                    and args(name, age)"/>

         <aop:around pointcut-ref="theExecutionOfSomeFooServiceMethod"
                  method="profile"/>

      </aop:aspect>
   </aop:config>

</beans>

如果我们有下面的驱动脚本,我们将在标准输出上得到如下的输出:

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import x.y.service.FooService;

public final class Boot {

   public static void main(final String[] args) throws Exception {
      BeanFactory ctx = new ClassPathXmlApplicationContext("x/y/plain.xml");
      FooService foo = (FooService) ctx.getBean("fooService");
      foo.getFoo("Pengo", 12);
   }
}

通知顺序

当同一个切入点(执行方法)上有多个通知需要执行时,执行顺序的规则如 Section 6.2.4.7, “通知顺序”所述。切面的优先级通过给切面的支持bean增加 Order注解或者使切面的支持bean实现 Ordered接口来决定。   

引入

引入(在AspectJ中称为inter-type声明)允许一个切面声明一个通知对象实现指定接口, 并且提供了一个接口实现类来代表这些对象。

引入的定义使用aop:aspect中的aop:declare-parents元素。 该元素用于声明所匹配的类型有一个新的父类型(所以有了这个名字)。 例如,给定接口UsageTracked, 以及这个接口的一个实现类 DefaultUsageTracked, 下面的切面声明所有实现service接口的类同时实现 UsageTracked 接口。(比如为了通过JMX输出统计信息)

<aop:aspect id="usageTrackerAspect" ref="usageTracking">

  <aop:declare-parents
      types-matching="com.xzy.myapp.service.*+"
      implement-interface="com.xyz.myapp.service.tracking.UsageTracked"
      default-impl="com.xyz.myapp.service.tracking.DefaultUsageTracked"/>
 
  <aop:before
    pointcut="com.xyz.myapp.SystemArchitecture.businessService()
              and this(usageTracked)"
    method="recordUsage"/>
 
</aop:aspect>

usageTracking bean的支持类可以包含下面的方法:

public void recordUsage(UsageTracked usageTracked) {
    usageTracked.incrementUseCount();
}

要实现的接口由implement-interface属性来指定。  types-matching属性的值是一个AspectJ类型模式:任何匹配类型的bean都会实现  UsageTracked 接口。注意在上面前置通知的例子中, serevice bean可以直接用作UsageTracked接口的实现。 如果以编程形式访问一个bean,你可以这样来写:

UsageTracked usageTracked = (UsageTracked) context.getBean("myService");
分享到:
评论
2 楼 liyixing1 2014-09-23  
kapaseker 写道
你好意思??翻译官方文档???

1 楼 kapaseker 2014-08-15  
你好意思??翻译官方文档???

相关推荐

    SpringAop xml方式配置通知

    **Spring AOP XML方式配置通知** 在Java世界中,Spring框架是广泛应用的IoC(Inversion of Control)和AOP(Aspect Oriented Programming)容器。AOP允许开发者定义“方面”,这些方面可以封装关注点,如日志、事务...

    spring aop xml 实例

    Spring AOP主要通过两种方式实现:XML配置和注解。本实例主要探讨的是使用XML配置的方式来实现AOP。XML配置虽然相比注解方式略显繁琐,但它提供了更大的灵活性,尤其是在需要对多个类或方法应用相同通知(Advice)时...

    spring aop管理xml版

    **Spring AOP 管理XML版详解** 在Spring框架中,面向切面编程(Aspect Oriented Programming,简称AOP)是一种重要的设计模式,它扩展了传统的面向对象编程(OOP),使得我们可以将关注点分离,特别是那些横切关注...

    spring aop注解方式、xml方式示例

    下面将详细介绍Spring AOP的注解方式和XML配置方式。 ### 注解方式 #### 1. 定义切面(Aspect) 在Spring AOP中,切面是包含多个通知(advisors)的类。使用`@Aspect`注解标记切面类,例如: ```java @Aspect ...

    spring aop jar 包

    在使用Spring AOP时,我们可以通过XML配置或注解的方式来定义切面。例如,可以使用`@Aspect`注解定义一个切面类,`@Before`、`@After`等注解来声明通知,`@Pointcut`定义切点表达式。 在实际开发中,Spring AOP广泛...

    Spring AOP 16道面试题及答案.docx

    Spring支持两种AOP的实现方式:Spring AspectJ注解风格和Spring XML配置风格。使用AspectJ注解风格是最常见的,它允许开发者直接在方法上使用注解来定义切面。 Spring AOP中有五种不同类型的的通知(Advice): 1....

    spring aop xml实现

    XML配置是Spring AOP早期版本中主要的配置方式,虽然在Spring 4.x及以后版本中,基于注解的配置更加常见,但理解XML配置仍然是学习AOP的基础。 首先,我们需要了解AOP的基本概念: 1. 切面(Aspect):一个关注点的...

    简单spring aop 例子

    Spring AOP(面向切面编程)是Spring框架的重要组成部分,它提供了一种模块化和声明式的方式来处理系统中的交叉关注点问题,如日志、事务管理、安全性等。本示例将简要介绍如何在Spring应用中实现AOP,通过实际的...

    Spring AOP完整例子

    在Spring XML配置中,我们可以使用`&lt;aop:config&gt;`元素来定义切点表达式,然后使用`&lt;aop:aspect&gt;`元素来声明切面,并将通知方法与切点关联起来。此外,还可以使用注解驱动的配置,通过`@EnableAspectJAutoProxy`注解...

    spring aop依赖jar包

    现在,我们回到主题——"springaop依赖的jar包"。在Spring 2.5.6版本中,使用Spring AOP通常需要以下核心jar包: - `spring-aop.jar`:这是Spring AOP的核心库,包含了AOP相关的类和接口。 - `spring-beans.jar`:...

    用xml配置的方式进行SpringAOP开发

    本篇文章主要讲解如何通过XML配置来实现Spring AOP的开发。 首先,了解AOP的基本概念。AOP通过“切面”(Aspect)来封装横切关注点,切面由“通知”(Advice)和“连接点”(Join Point)组成。通知是在特定连接点...

    Spring Aop四个依赖的Jar包

    例如,可以通过以下XML配置启用Spring AOP: ```xml &lt;aop:aspectj-autoproxy /&gt; ``` 然后,我们可以定义切面、切点和通知,比如: ```xml &lt;aop:config&gt; &lt;aop:aspect ref="loggingAspect"&gt; &lt;aop:before method...

    Spring AOP实现机制

    Spring AOP的配置可以通过XML或注解方式进行: - **XML配置**: - 在`&lt;aop:config&gt;`标签内定义切面,`&lt;aop:pointcut&gt;`定义切入点,`&lt;aop:advisor&gt;`定义通知。 - `&lt;aop:aspect&gt;`标签用于定义完整的切面,包括切入...

    spring AOP依赖三个jar包

    在这个版本中,Spring AOP支持基于注解的切面定义,比如`@Aspect`、`@Before`、`@After`等,同时也支持基于XML配置的切面定义。这个jar包使得Spring应用程序能够方便地利用AOP特性,无需引入额外的编译工具或构建...

    Spring AOP 的实现例子(基于XML配置实现)

    XML配置是Spring AOP早期的主要实现方式,虽然现在有更简洁的注解式配置,但理解XML配置方式对于深入理解AOP原理仍然很有帮助。下面我们将详细探讨如何通过XML配置实现Spring AOP。 首先,我们需要在Spring配置文件...

    spring aop的demo

    在`springAop1`这个压缩包中,可能包含了一个简单的应用示例,展示了如何定义一个切面类,以及如何在该类中定义通知方法。例如,我们可能会看到一个名为`LoggingAspect`的类,其中包含了`@Before`注解的方法,用于在...

    基于xml的SpringAOP实例

    在基于XML的配置方式下,Spring AOP提供了直观且灵活的声明式方法来实现这些关注点的分离,使得业务逻辑代码更为简洁。 在Spring AOP中,我们首先需要定义一个切面(Aspect),它包含了若干个通知(Advice)。通知...

    spring AOP 引入jar包,spring IOC 引入Jar包

    Spring AOP 和 Spring IOC 是 Spring 框架的两个核心组件,它们对于任何基于 Java 的企业级应用开发都至关重要。Spring AOP(面向切面编程)允许开发者在不修改源代码的情况下,通过“切面”来插入新的行为或增强已...

    springAop的配置实现

    Spring AOP通过XML配置文件提供了灵活的方式来定义和管理切面、切入点和通知,使得我们可以轻松地在应用程序中实现横切关注点的解耦。了解和掌握Spring AOP的配置实现,有助于提升我们构建松散耦合、易于维护的系统...

    spring aop用到jar包.rar

    如果涉及到XML配置,`spring-expression.jar`(Spring表达式语言,SpEL)也可能包含在内,它允许在配置中进行复杂的条件判断和对象操作。 总的来说,这个压缩文件"spring aop用到jar包.rar"包含了实现Spring AOP所需...

Global site tag (gtag.js) - Google Analytics