Spring AOP: Spring之面向方面编程

完整的中文翻译文档地址: http://www.jactiongroup.net/reference/html/aop.html
由spring.jactiongroup.net强力提供,正在完善翻译中。如果你觉得你对技术翻译有熟练的技巧,请与他们共同继续。

Chapter 5. Spring AOP: Spring之面向方面编程
5.1. 概念
面向方面编程 (AOP) 提供另外一种关于程序结构的思维完善了OOP。 OO将应用程序分解成 各个层次的对象,而AOP将程序分解成各个方面 或者说 关注点 。 这使得可以模块化诸如事务管理等这些横切多个对象的关注点。(这些关注点经常用术语 横切关注点表达。)

Spring的一个关键组件就是AOP框架。 Spring IoC容器(BeanFactory 和ApplicationContext)不依赖于AOP, 意味着如果你不需要使用AOP你可以不用,AOP提供一个有效 的中间件解决方案,完善了Spring IoC。

AOP在Spring中的使用:

提供声明式企业服务,特别是做为EJB声明式服务的替代品。这些服务中最重要的是 声明式事务管理,这个服务建立在Spring的事务管理抽象之上

允许用户实现自定义的方面,用AOP完备他们的OOP的使用。

这样你可以把Spring AOP视着一项授权技术,使Spring提供无需EJB的声明式事务管理;或者 使用Spring AOP框架的全部功能来实现自定义的方面。

如果你只对通用的声明式服务或者预先打包的声明式中间件服务如pooling,你不需要直接使用 Spring AOP,可以跳过本章的大部分.
5.1.1. AOP概念
让我从定义一些重要的AOP概念开始。这些术语不是Spring特有的。不幸的是,Spring的术语 不是特别地直观。而且,如果Spring使用自己的术语,这将使人更加迷惑。

Aspect方面: 一个关注点的模块化,这个关注点实现可能 另外横切多个对象。事务管理是J2EE应用中横切关注点中一个很好的例子。方面用Spring的 Advisor或拦截器实现。

Joinpoint连接点: 程序执行过程中明确的点,如方法的调 用或特定的异常被抛出。

Advice通知: 在特定的连接点AOP框架执行的动作。各种类 型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架 包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器 链。

Pointcut切入点: 指定一个通知将被引发的一系列连接点 的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。

Introduction引入: 添加方法或字段到通知化类。 Spring允许引入新的接口到通知化对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。

Target object目标对象: 包含连接点的对象。也被用来 引用通知化或代理化对象。

AOP proxy AOP代理: AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

Weaving织入: 组装方面创建通知化对象。这可以在编译时 完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样, 运行时完成织入。

各种通知类型包括:

Around通知: 包围一个连接点的通知,如方法调用。这是最 强大的通知。Aroud通知在方法调用前后完成自定义的行为。它们负责选择继续执行连接点或直接 返回它们自己的返回值或抛出异常来短路执行。

Before通知: 在一个连接点之前执行的通知,但这个通知 不能阻止流程继续执行到连接点(除非它抛出一个异常)。

Throws通知: 在方法抛出异常时执行的通知。Spring提供 强类型的Trows通知,因此你可以书写代码捕获感兴趣的异常(和它的子类),不需要从Throwable 或Exception转型。

After returning通知: 在连接点正常完成后执行的通知, 例如,如果一个方法正常返回,没有抛出异常。

Around通知是最通用的通知类型。大部分基于拦截器的AOP框架如Nanning和JBoss4只提供 Around通知。

如同AspectJ,Spring提供所有类型的通知,我们推荐你使用最为合适的通知类型来实现需 要的行为。例如,如果只是需要用一个方法的返回值来更新缓存,你最好实现一个after returning 通知而不是around通知,虽然around通知也能完成同样的事情。使用最合适的通知类型提供能减少潜 在错误的简单的编程模型。例如你不需要调用用在around通知中的MethodInvocation的 proceed()方法,因此就不操作调用失败的情况。

切入点的概念是AOP的关键,AOP和以前的技术区别于提供了拦截器。切入点使通知独立于OO的 层次选定目标。例如,around通知提供的声明式事务管理可以被应用到跨越多个对象的方法上。这样切 入点构成了AOP的结构要素。

5.1.2. Spring AOP性能
Spring AOP用纯Java实现。不需要特别的编译过程。Spring AOP不需要控制类装载器层次, 因此适用于J2EE web容器或应用服务器。

Spring目前支持方法调用的拦截器。字段拦截器没有实现,虽然加入字段拦截器支持并不破坏 Spring AOP核心API。

字段拦截器在违反OO封装原则方面存在争论。我们不认为这在应用程序开发中是明智的。如 果你需要使用字段拦截器,考虑使用AspectJ。
Spring提供代表切入点或各种通知类型的类。Spring使用术语一个对象的 advisor来表示一个方面,包含一个通知和一个指定特定连接点的切入点。

各种通知类型有MethodInterceptor (来自AOP联盟的拦截器API)和定义在org.springframework.aop包中的 通知接口。所有通知必须实现org.aopalliance.aop.Advice标签接口。 支持取出就可使用的通知有 MethodInterceptor、 ThrowsAdvice、 BeforeAdvice和 AfterReturningAdvice。我们将在下面详细讨论这些通知类型。

Spring实现了AOP联盟的拦截器接口( http://www.sourceforge.net/projects/aopalliance). Around通知必须实现AOP联盟的org.aopalliance.intercept.MethodInterceptor 接口。这个接口的实现可以运行在Spring或其他AOP联盟兼容的实现中。目前JAC实现了AOP联盟的接 口,Nanning和Dynaop可能在2004年早期实现。

Spring实现AOP的途径不同其他大部分AOP框架。它的目标不是提供及其完善的AOP实现( 虽然Spring AOP非常强大);而是提供一个和Spring IoC紧密整合的AOP实现,帮助解决企业应用 中的常见问题。因此,例如Spring AOP的功能通常是和Spring IoC容器联合使用的。AOP通知是用普通 的bean定义语法来定义的(虽然可以使用"autoproxying"功能);通知和切入点本身由Spring IoC 管理:一个重要的其他AOP实现的区别。有些事不要用Spring AOP很容易或很高效地实现,如果通知化 非常细粒度的对象。这种情况AspectJ可能是最合适的选择。但是,我们的经验是Spring针对J2EE应 用中大部分能用AOP解决的问题提供了一个优秀的解决方案。
5.1.3. Spring中AOP代理
Spring默认使用JDK动态代理实现AOP代理。这使得任何接口或 接口的集合能够被代理。

Spring也可以是CGLIB代理。这可以代理类,而不是接口。CGLIB被默认使用在业务对象没有 实现一个接口。但是作为一针对接口编程而不是类编程良好实践,业务对象 通常实现一个或多个业务接口。

也可以强制使用CGLIB:我们将在下面讨论,我们也会解释为什么你不想这么做。

Spring 1.0后,Spring可能提供额外的AOP代理的类型,包括完全的生成的类。这将影响 编程模型。
5.2. Spring的切入点
让我们看看Spring如何处理重要的切入点的概念。

5.2.1. 概念
Spring的切入点模型能够使切入点独立于通知类型被重用。 同样的切入点有可能将不同的 通知作为目标。

org.springframework.aop.Pointcut 接口是重要的接口, 用来指定通知到特定的类和方法目标。完整的接口定义如下:

public interface Pointcut {

  ClassFilter getClassFilter();

  MethodMatcher getMethodMatcher();

}
将Pointcut接口分成两个部分允许类和方法匹配的重用和细粒度的 组合操作(如和另一个方法匹配器执行一个”并“的操作)。

ClassFilter接口被用来将切入点约束到一个给定的目标类的集合。 如果matches()永远返回true,所有的目标类都将被匹配。

public interface ClassFilter {

  boolean matches(Class clazz);
}
MethodMatcher接口通常更加重要。完整的接口如下:

public interface MethodMatcher {

  boolean matches(Method m, Class targetClass);

  boolean isRuntime();

  boolean matches(Method m, Class targetClass, Object[] args);
}
matches(Method, Class) 方法被用来测试这个切入点是否匹 配目标类的给定方法。这个演算可以在AOP代理被创建的时候执行,避免在所有方法调用时都需要进行 测试。如果对一个给定方法的2个参数的匹配方法返回true,并且MethodMatcher的 isRuntime()返回true,3个参数的匹配方法将在每次方法调用的时候被调用。这使 切入点能够在目标通知被执行之前立即查看传递给方法调用的参数。

大部分MethodMatcher都是静态的,意味着isRuntime()方法 返回false。这种情况下3个参数的匹配方法永远不会被调用。

如果可能,尽量使切入点是静态的,使当AOP代理被创建时,AOP框架能够缓存切入点的 演算结果。
5.2.2. 切入点的运算
Spring支持的切入点的运算有: 著名的 并 和 交。

并表示只要任何一个切入点匹配的方法。

交表示两个切入点都要匹配的方法。

并通常比较有用。

切入点可以用org.springframework.aop.support.Pointcuts 类的静态方法来组合,或者使用同一个包中的ComposablePointcut类。

5.2.3. 实用切入点实现
Spring提供几个实用的切入点实现。一些取出即可使用。另一些需要子类化来实现应用相 关的切入点。

5.2.3.1. 静态切入点
静态切入点基于方法和目标类,并且不考虑方法的参数。静态切入点足够满足大多数情况 的使用。Spring可以只在方法第一次被调用的时候演算一次静态切入点,不需要在每次方法调用 的时候演算切入点。

让我看一下包含在Spring中一些静态切入点的实现。

5.2.3.1.1. 正规表达式切入点
一个很显然的指定静态切入点的方法是正规表达式。除了Spring以外,的AOP框架实 现了这一点。org.springframework.aop.support.RegexpMethodPointcut 是一个通用的正规表达式切入点,使用Perl 5的正规表达式的语法。

使用这个类你可以提供一个模式的列表。如果任何一个匹配,那个切入点将被演算成 true。(所以结果是这些切入点的有效并集)。

用法如下:

<bean id="settersAndAbsquatulatePointcut"
  class="org.springframework.aop.support.RegexpMethodPointcut">
  <property name="patterns">
    <list>
        <value>.*get.*</value>
        <value>.*absquatulate</value>
    </list>
  </property>
</bean>
RegexpMethodPointcut一个实用子类, RegexpMethodPointcutAdvisor, 允许我们同时引用一个通知。 (记住通知可以是拦截器,before通知,throws通知等等。)这简化了bean的装配,因为一个 就可以同时为切入点和advisor服务,如下所示:

<bean id="settersAndAbsquatulateAdvisor"
  class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
  <property name="interceptor">
    <ref local="beanNameOfAopAllianceInterceptor"/>
  </property>
  <property name="patterns">
    <list>
        <value>.*get.*</value>
        <value>.*absquatulate</value>
    </list>
  </property>
</bean>
RegexpMethodPointcutAdvisor可以和任何通知类型 联用。

The RegexpMethodPointcut类需要Jakarta ORO正规表达式包。
5.2.3.1.2. 属性驱动的切入点
一个重要的静态切入点的类型是元数据驱动的 切入点。 这使用元数据属性的值:典型地,使用源代码级元数据。

5.2.3.2. 动态切入点
动态切入点的演算代价比静态切入点高的多。它们不仅考虑静态信息,还有考虑方法的 参数。这意味着它们必须在每次方法调用的时候都被演算;结果不能 缓存,因为参数是变化的。

这个主要的例子就是control flow切入点。

5.2.3.2.1. Control flow切入点
Spring的control flow切入点概念上和Aspectj的cflow 切入点一致,虽然没有其那么强大(当前没有方法指定一个切入点在另一个切入点前执行)。 一个control flow切入点匹配当前的调用栈.例如,它可以在连接点被 com.mycompany.web包中一个方法或者被 SomeCaller类调用的时候触发。Control flow切入点用 org.springframework.aop.support.ControlFlowPointcut 类指定。

Note
Control flow切入点运行时演算比其他的动态切入点代价高昂很多。Java 1.4中, 代价是其他动态切入点的5倍。Java 1.3超过10倍。


5.2.4. 切入点超类
Spring提供非常实用的切入点的超类帮助你实现你自己的切入点。

因为静态切入点非常实用,你很可能子类化StaticMethodMatcherPointcut,如下所示。 这只需要实现一个抽象方法(虽然可以改写其它的方法来自定义行为)。

class TestStaticPointcut extends StaticMethodMatcherPointcut {

  public boolean matches(Method m, Class targetClass) {
    // return true if custom criteria match
  }
}
也有动态切入点的超类。

Spring 1.0 RC2或以上版本,可以使用和任何类型通知一起使用自定义切入点。

5.2.5. 自定义切入点
因为Spring的切入点是Java类,而不是语言特性(如AspectJ),可以声明自定义切入点, 无论静态还是动态。但是,没有如AspectJ语法书写的成熟的切入点的表达式的直接支持。不过, Spring的自定义切入点可以任意的负责。

后续版本的Spring可能提供如JAC提供的”语义切入点“的支持:例如,“所有更改目标对象 实例变量的方法”。
5.3. Spring的通知类型
现在让我们看看Spring AOP是如何处理通知的。

5.3.1. 通知的生命周期
Spring的通知可以跨越多个通知化对象共享,或者每个通知化对象唯一。这分别对应 per-class或per-instance 通知。

Per-class通知使用最为广泛。它适合于通用的通知,如事务adisor。它们不依赖被代理 的对象的状态或添加新的状态。它们仅仅作用于方法和方法的参数。

Per-instance通知适合于导入,来支持混入(mixin)。在这种情况下,通知添加状态到 被代理的对象。

可以在同一个AOP代理中混合使用共享和per-instance通知。

5.3.2. Spring中通知类型
Spring提供几种现成的通知类型并可扩展来提供任意的通知类型。让我们看看基本概念和 标准的通知类型。

5.3.2.1. Interception around advice
Spring中最基本的通知类型是interception around advice .

Spring使用方法拦截器的around通知是和AOP联盟接口兼容的。实现around通知的 MethodInterceptor应该实现下面的接口:

public interface MethodInterceptor extends Interceptor {

  Object invoke(MethodInvocation invocation) throws Throwable;
}
invoke()方法的MethodInvocation 参数暴露将被调用的方法、目标连接点、AOP代理和传递给被调用方法的参数。 invoke()方法应该返回调用的结果:连接点的返回值。

一个简单MethodInterceptor实现看起来如下:

public class DebugInterceptor implements MethodInterceptor {

  public Object invoke(MethodInvocation invocation) throws Throwable {
    System.out.println("Before: invocation=[" + invocation + "]");
    Object rval = invocation.proceed();
    System.out.println("Invocation returned");
    return rval;
  }
}
注意MethodInvocation的proceed()方法的调用。 这沿着连接点继续执行下面的拦截器。大部分拦截器将调用这个方法,并返回它的返回值。但是, 一个MethodInterceptor,和任何around通知一样,能够返回不同的值或者抛出一个异常,而 不是调用proceed方法。但是,没有好的原因你并不会想这么做。

MethodInterceptor提供了和其他AOP联盟兼容的AOP实现的交互能力。这一节下面 要讨论的其他的通知类型实现了AOP共通的概念,但是以Spring特定的方式。虽然使用最特定的 通知类型有优势,但如果你有可能在其他的AOP框架使用这个方面请坚持使用MethodInterceptor around通知类型。注意目前切入点是不能在框架间交互操作的,并且AOP联盟目前也没有定义切入 点接口。
5.3.2.2. Before通知
一个很简单的通知类型是before通知。 这个通知不需要一个MethodInvocation对象,因为它在进入一个方法 之前被调用。

Before通知的主要有点是它不需要调用proceed() 方法, 并且没有无意中忘掉继续执行拦截器链的可能性。

MethodBeforeAdvice接口如下所示。 (Spring的API设计允许字段的before通知,虽然一般的对象都可以应用字段拦截,但Spring 有可能永远不会实现它)。

public interface MethodBeforeAdvice extends BeforeAdvice {

  void before(Method m, Object[] args, Object target) throws Throwable;
}
注意返回类型是void。 Before通知可以在连接点执行之前 插入自定义的行为,但是不能改变返回值。如果一个before通知抛出一个异常,这将中断拦截器 链的进一步执行。这个异常将沿着拦截器链后退着向上传播。如果这个异常是未被检查的,或者 它在被调用的方法的签名中,它将会被直接传递给客户;否则,它将被AOP代理包装到一个未被 检查的异常里。

下面是Spring 中一个before通知的例子,这个例子计数所有正常返回的方法:

public class CountingBeforeAdvice implements MethodBeforeAdvice {
  private int count;
  public void before(Method m, Object[] args, Object target) throws Throwable {
    ++count;
  }

  public int getCount() {
    return count;
  }
}
Before通知可以被用于任何类型的切入点。
5.3.2.3. Throws通知
Throws通知在连接点返回后如果连接点抛出 异常时被调用。Spring提供强类型的thrwos通知。注意这意味着 org.springframework.aop.ThrowsAdvice接口不包含任何方法: 它是一个标识给定的对象实现了一个或多个强类型的throws通知方法的标记接口。这些方法形式 如下:

afterThrowing([Method], [args], [target], subclassOfThrowable)
只有最后一个参数是必需的。 这样从一个参数到四个参数,依赖于通知是否对方法和方法 的参数感兴趣。下面是throws通知的例子。

这个通知会被调用,如果RemoteException异常(包括子 类):

public class RemoteThrowsAdvice implements ThrowsAdvice {

  public void afterThrowing(RemoteException ex) throws Throwable {
    // Do something with remote exception
  }
}
下面的通知会被调用,如果一个ServletException异常 被抛出。和上面的通知不一样,它声明了四个参数,所以它可以方法被调用的方法,方法的参数 和目标对象:

public static class ServletThrowsAdviceWithArguments implements ThrowsAdvice {

  public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
    // Do something will all arguments
  }
}
最后一个例子演示了如何在一个类中使用两个方法来同时处理 RemoteException和ServletException 异常。任意个数的throws方法可以被组合在一个类中。

public static class CombinedThrowsAdvice implements ThrowsAdvice {

  public void afterThrowing(RemoteException ex) throws Throwable {
    // Do something with remote exception
  }

  public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
    // Do something will all arguments
  }
}
Throws通知可被用于任何类型的切入点。
5.3.2.4. After Returning通知
Spring中的after returning通知必须实现 org.springframework.aop.AfterReturningAdvice 接口, 如下所示:

public interface AfterReturningAdvice extends Advice {

  void afterReturning(Object returnValue, Method m, Object[] args, Object target)
        throws Throwable;
}
After returning通知可以访问返回值(不能改变)、被调用的方法、方法的参数和 目标对象。

下面的after returning通知统计所有成功的没有抛出异常方法调用:

public class CountingAfterReturningAdvice implements AfterReturningAdvice {
  private int count;

  public void afterReturning(Object returnValue, Method m, Object[] args, Object target) throws Throwable {
    ++count;
  }

  public int getCount() {
    return count;
  }
}
这方法不改变执行路径。如果它抛出一个异常,这个异常而不是返回值将被沿着拦截器链 向上抛出。

After returning通知可被用于任何类型的切入点。
5.3.2.5. Introduction通知
Spring将introduction通知看着一种特殊类型的拦截通知。

Introduction需要一个IntroductionAdvisor, 和IntroductionInterceptor, IntroductionInterceptor实现了下面的接口:

public interface IntroductionInterceptor extends MethodInterceptor {

  boolean implementsInterface(Class intf);
}
继承自AOP联盟MethodInterceptor接口的 invoke()方法必须实现导入:也就是说,如果被调用的方法是在 导入的接口中,导入拦截器负责处理这个方法调用,它不能调用proceed() 方法。

Introduction通知不能被用于任何切入点,因为它只能作用于类级别,而不是方法级别。 你可以只用InterceptionIntroductionAdvisor来实现导入通知,它有下面的方法:

public interface InterceptionIntroductionAdvisor extends InterceptionAdvisor {

  ClassFilter getClassFilter();

  IntroductionInterceptor getIntroductionInterceptor();

  Class[] getInterfaces();
}
这里没有MethodMatcher,因此也没有和导入通知关联的 Pointcut。只有类过滤是合乎逻辑的。

getInterfaces()方法返回advisor导入的接口。

让我们看看一个来自Spring测试套件中的简单例子。我们假设想要导入下面的接口到一个 或者多个对象中:

public interface Lockable {
  void lock();
  void unlock();
  boolean locked();
}
这个例子演示了一个mixin。我们想要能够 将通知化对象转型到Lockable,不管它们的类型,并且调用call和uncall方法。如果我们调用 lock()方法,我们希望所有setter方法抛出LockedException异常。 这样我们能添加一个方面提供使对象不可变的能力,而不需要它们知道这一点:一个很好的AOP例 子。

首先,我们需要一个做大量转化的IntroductionInterceptor。 在这里,我们继承 org.springframework.aop.support.DelegatingIntroductionInterceptor 实用类。我们可以直接实现IntroductionInterceptor,但是大多数情况下 DelegatingIntroductionInterceptor是最合适的。

DelegatingIntroductionInterceptor的设计是将导入 委托到真正实现导入接口的接口,隐藏完成这些工作的拦截器的使用。委托可以使用构造方法参数 放到任何对象中;默认的委托就是这样实现的(当无参数的构造方法被使用时)。这样在下面的 例子里,委托是DelegatingIntroductionInterceptor的子类 LockMixin。给定一个委托(默认是自身) DelegatingIntroductionInterceptor实例寻找被这个委托(而不 是IntroductionInterceptor)实现的所有接口,并支持它们中任何一个导入。子类如 LockMixin也可能调用suppressInterflace(Class intf) 方法隐藏不应暴露的接口。然而,不管IntroductionInterceptor 准备至此多少接口,IntroductionAdvisor将控制哪个接口将实际 上被暴露。一个导入的接口将隐藏目标的同一个接口的所有实现。

这样,LockMixin子类化DelegatingIntroductionInterceptor 并自己实现Lockable。父类自动选择支持导入的Lockable,所以我们不需要指定这一点。 用这种方法我们可以导入任意数量的接口。

注意locked实例变量的使用。这有效地添加额外的状态到目标 对象。

public class LockMixin extends DelegatingIntroductionInterceptor
  implements Lockable {

  private boolean locked;

  public void lock() {
    this.locked = true;
  }

  public void unlock() {
    this.locked = false;
  }

  public boolean locked() {
    return this.locked;
  }

  public Object invoke(MethodInvocation invocation) throws Throwable {
    if (locked() && invocation.getMethod().getName().indexOf("set") == 0)
        throw new LockedException();
    return super.invoke(invocation);
  }

}
通常不要需要改写invoke()方法:如果是导入的方法, DelegatingIntroductionInterceptor的实现将调用委托的方法, 否则继续沿着连接点处理,通常这就足够了。在现在的情况下,我们需要添加一个检查:在上锁 状态下没有setter方法能被调用。

必需的导入advisor是很简单的。所有它需要的就是持有一个独立的 LockMixin实例,并指定导入的接口,在这里就是 Lockable。一个稍微复杂一点例子可能需要一个导入拦截器(可以 定义成原型)的引用:在这里,LockMixin没有相关配置,所以我们简单地 使用new来创建它。

public class LockMixinAdvisor extends DefaultIntroductionAdvisor {

  public LockMixinAdvisor() {
    super(new LockMixin(), Lockable.class);
  }
}
我们可以非常简单地应用这个advisor:它不需要任何配置。(但是,有一点 是必要的:不可能在没有IntroductionAdvisor 的情况下使用IntroductionInterceptor。) 和导入一样,通常 advisor必须是针对每个实例的,并且是有状态的。对每个通知化的对象,我们需要不同的 LockMixinAdvisor实例和LockMixin。 这个advisor包含部分通知化对象的状态。

和其他advisor一样,我们可以编程式地使用这个advisor,使用 Advised.addAdvisor() 方法,或者在XML中配置(推荐方式)。 所有代理创建选择下面讨论,包括“自动代理创建者”,正确地处理导入和有状态的混入。

5.4. Spring中的advisor
在Spring中,一个advisor就是一个aspect的完整的模块化表示。 一般地,一个advisor包括advice和poitcut 2个方面。

撇开导入的特殊情形,任何advisor可被用于任何通知。 org.springframework.aop.support.DefaultPointcutAdvisor 是最通用的advisor类。例如,它可以和MethodInterceptor、 BeforeAdvice或者ThrowsAdvice一起使 用。

Spring中在一个AOP代理中混合advisor和通知是可能的。例如,你可以在一个代理配置中 使用一个拦截的around通知、throws通知和before通知和:Spring将自动创建必要的拦截器链。

5.5. 用ProxyFactoryBean创建AOP代理
如果你在为你的业务对象使用Spring的IoC容器(例如ApplicationContext或者BeanFactory), 你应该会或者你愿意会使用Spring的aop FactoryBean(记住,factory bean引入了一个间接层, 它能创建不同类型的对象).

在spring中创建AOP proxy的基本途径是使用org.springframework.aop.framework.ProxyFactoryBean. 这样可以对pointcut和advice作精确控制。但是如果你不需要这种控制,那些简单的选择可能更适合你。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值