快捷搜索:

使用Spring进行面向切面编程3(AOP)

6.4.1. Spring AOP照样完全用AspectJ?

做能起感化的最简单的事。Spring AOP比完全应用AspectJ加倍简单,由于它不必要引入AspectJ的编译器/织入器到你开拓和构建历程中。 假如你仅仅必要在Spring bean上看护履行操作,那么Spring AOP是相宜的选择。假如你必要看护domain工具或其它没有在Spring容器中 治理的随意率性工具,那么你必要应用AspectJ。假如你想看护除了简单的措施履行之外的连接点(如:调用连接点、字段get或set的连接点等等), 也必要应用AspectJ。

当应用AspectJ时,你可以选择应用AspectJ说话(也称为“代码风格”)或@AspectJ评释风格。 假如切面在你的设计中扮演一个很大年夜的角色,并且你能在Eclipse中应用AspectJ Development Tools (AJDT), 那么首选AspectJ说话 :- 由于该说话专门被设计用来编写切面,以是会更清晰、更简单。假如你没有应用 Eclipse,或者在你的利用中只有很少的切面并没有作为一个主要的角色,你或许应该斟酌应用@AspectJ风格 并在你的IDE中附加一个通俗的Java编辑器,并且在你的构建脚本中增添切面织入(链接)的段落。

6.4.2. Spring AOP中应用@AspectJ照样XML?

假如你选择应用Spring AOP,那么你可以选择@AspectJ或者XML风格。总的来说,假如你应用Java 5, 我们建议应用@AspectJ风格。显然假如你不是运行在Java 5上,XML风格是最佳选择。XML和@AspectJ 之间权衡的细节将鄙人面进行评论争论。

XML风格对现有的Spring用户来说加倍习气。它可以应用在任何Java级别中(参考连接点表达式内部的命名连接点,虽然它也必要Java 5) 并且经由过程纯挚的POJO来支持。当应用AOP作为对象来设置设置设备摆设摆设企业办事时(一个好的例子是当你觉得连接点表达式是你的设置设置设备摆设摆设中的一部分时, 你可能想零丁变动它)XML会是一个很好的选择。对付XML风格,从你的设置设置设备摆设摆设中可以清晰的注解在系统中存在那些切面。

XML风格有两个毛病。第一是它不能完全将需求实现的地方封装到一个位置。DRY原则中说系统中的每一项常识都必须具有单一、无歧义、势力巨子的表示。 当应用XML风格时,若何实现一个需求的常识被瓜分到支撑类的声明中以及XML设置设置设备摆设摆设文件中。当应用@AspectJ风格时就只有一个零丁的模块 -切面- 信息被封装了起来。 第二是XML风格同@AspectJ风格所能表达的内容比拟有更多的限定:仅仅支持"singleton"切面实例模型,并且不能在XML中组合命名连接点的声­明。 例如,在@AspectJ风格中我们可以编写如下的内容:

@Pointcut(execution(* get*()))

public void propertyAccess() {}

@Pointcut(execution(org.xyz.Account+ *(..))

public void operationReturningAnAccount() {}

@Pointcut(propertyAccess() && operationReturningAnAccount())public void accountPropertyAccess() {}

在XML风格中能声明开首的两个连接点:

aop:pointcut id="propertyAccess"

expression="execution(* get*())"/>

aop:pointcut id="operationReturningAnAccount"expression="execution(org.xyz.Account+ *(..))"/>

然则不能经由过程组合这些来定义accountPropertyAccess连接点

@AspectJ风格支持其它的实例模型以及更富厚的连接点组合。它具有将将切面维持为一个模块单元的优点。 还有一个优点便是@AspectJ切面能被Spring AOP和AspectJ两者都理解 - 以是假如稍后你觉得你必要AspectJ 的能力去实现附加的需求,那么你异常轻易转移到基于AspectJ的道路。总而言之,我们更爱好@AspectJ风格只要你有切面 去做越过简单的“设置设置设备摆设摆设”企业办事之外的工作。

6.5. 混杂切面类型

我们完全可以混杂应用以下几种风格的切面定义:应用自动代理的@AspectJ 风格的切面,schema-defined的切面,和用声明的advisor,以致是应用Spring 1.2风格的代理和拦截器。 因为以上几种风格的切面定义的都应用了相同的底层机制,是以可以很好的共存。

6.6. 代理机制

Spring AOP部分应用JDK动态代理或者CGLIB来为目标工具创建代理。(建议只管即便应用JDK的动态代理)

假如被代理的目标工具实现了至少一个接口,则会应用JDK动态代理。所有该目标类型实现的接口都将被代理。若该目标工具没有实现任何接口,则创建一个CGLIB­代理。

假如你盼望强制应用CGLIB代理,(例如:盼望代理目标工具的所有措施,而不光是实现自接口的措施)那也可以。然则必要斟酌以下问题:

无法看护(advise)Final 措施,由于他们不能被覆写。

你必要将CGLIB 2二进制发行包放在classpath下面,与之相较JDK本身就供给了动态代理

强制应用CGLIB代理必要将的 proxy-target-class 属性设为true:

aop:config proxy-target-class="true">

...

aop:config>

当必要应用CGLIB代理和@AspectJ自动代理支持,请按照如下的要领设置的 proxy-target-class 属性:

6.7. 编程要领创建@AspectJ代理

除了在设置设置设备摆设摆设文件中应用或者来声明切面。 同样可以经由过程编程要领来创建代理看护(advise)目标工具。关于Spring AOP API的具体先容,请参看下一章。这里我们重点先容自动创建代理。

类 org.springframework.aop.aspectj.annotation.AspectJProxyFactory 可以为@AspectJ切面的目标工具创建一个代理。该类的基础用法异常简单,示例如下。请参看Javadoc获取更具体的信息。

// create a factory that can generate a proxy for the given target object

AspectJProxyFactory factory = new AspectJProxyFactory(targetObject);

// add an aspect, the class must be an @AspectJ aspect// you can call this as many times as you need with different aspects

factory.addAspect(SecurityManager.class);

// you can also add existing aspect instances, the type of the object supplied must be an @AspectJ aspectfactory.addAspect(usageTracker);

// now get the proxy object...

MyInterfaceType proxy = factory.getProxy();

6.8. 在Spring利用中应用AspectJ

到今朝为止本章评论争论的不停是纯Spring AOP。 在这一节里面我们将先容若何应用AspectJ compiler/weaver来代替Spring AOP或者作为它的弥补,由于有些时刻Spring AOP零丁供给的功能大概并不能满意你的必要。

Spring供给了一个小巧的AspectJ aspect library (你可以在法度榜样发行版本中零丁应用 spring-aspects.jar 文件,并将其加入到classpath下以应用此中的切面)。 Section 6.8.1, “在Spring中应用AspectJ来为domain object进行依附注入” 和 Section 6.8.2, “Spring中其他的AspectJ切面” 评论争论了该库和若何应用该库。 Section 6.8.3, “应用Spring IoC来设置设置设备摆设摆设AspectJ的切面” 评论争论了若何对经由过程AspectJ compiler织入的AspectJ切面进行依附注入。 着末Section 6.8.4, “在Spring利用中应用AspectJ Load-time weaving(LTW)”先容了应用AspectJ的Spring利用法度榜样若何装载期织入(load-time weaving)。

6.8.1. 在Spring中应用AspectJ来为domain object进行依附注入

Spring容器对application context中定义的bean进行实例化和设置设置设备摆设摆设。 同样也可以经由过程bean factory来为一个已经存在且已经定义为spring bean的工具利用所包孕的设置设置设备摆设摆设信息。 spring-aspects.jar中包孕了一个annotation-driven的切面,供给了能为任何工具进行依附注入的能力。 这样的支持旨在为 离开容器治理 创建的工具进行依附注入。 Domain object常常处于这样的情形:它们可能是经由过程 new 操作符创建的工具, 也可能是ORM对象查询数据库的返回结果工具。

包 org.springframework.orm.hibernate.support 中的类 DependencyInjectionInterceptorFactoryBean 可以让Spring为Hibernate创建并且设置设置设备摆设摆设prototype类型的domain object(应用自动装置或者确切命名的bean原型定义)。 当然,拦截器不支持设置设置设备摆设摆设你编程要领创建的工具而非检索数据库返回的工具。 其他framework也会供给类似的技巧。仍是那句话,Be Pragramatic选择能满意你需求的措施中最简单的那个。 请留意前面说起的类 没有 随Spring发行包一路宣布。 假如你盼望应用该类,必要从Spring CVS Respository高低载并且自行编译。 你可以在Spring CVS respository下的 'sandbox' 目录下找到该文件。

@Configurable 评释标记了一个类可以经由过程Spring-driven要领来设置设置设备摆设摆设。 在最简单的环境下,我们只把它算作标记评释:

您可能还会对下面的文章感兴趣: