第 6 章 集成AspectJ

6.1. 概述

Spring基于代理的AOP框架很适合处理一般的中间件和特定应用的问题。 然而,有时,更强大的AOP方案也是需要的,例如,如果我们需要给一个类增加 额外的字段, 或者通知(Advise)一个不是由Spring IoC容器创建的细粒度的对象。

We recommend the use of AspectJ in such cases. Accordingly, as of version 1.1, Spring provides a powerful integration with AspectJ.

因为Spring很好的整合了AspectJ,所以这种情况下我们推荐使用AspectJ。

6.2. 使用Spring IoC配置AspectJ

Spring/AspectJ集成最重要的部分是允许Spring的依赖注射来配置AspectJ的aspect。 这给方面(aspect)和对象(object)带来了类似的好处。例如:

  • Aspect不需要使用特定的配置机制;它们可以使用和整个应用相同的、一致的方法来配置。

  • •Aspect可以依赖应用对象。例如,一个权限aspect可以依赖一个权限管理对象,稍后我们可以看到例子。

  • 可以通过相关的Spring上下文(Context)获得一个aspect的引用(reference),这可以允许动态的aspect配置。

AspectJ 的方式可以通过设值方式(setter)的注入Java Bean的属性,也可以通过实现Spring的生命周期接口来实现,例如实现 BeanFactoryAware

值得注意的是,AspectJ不能使用构造器注入方式和方法注入方式, 这是由于aspect没有类似对象的构造器那样可以调用方法的原因。

6.2.1. “单例”aspect

大多数情况下,AspectJ的aspect是单例的,每个类装载器一个实例, 这个单一的实例负责通知(advising)多个对象实例。

Spring IoC容器不能实例化aspect,因为,aspect没有可调用的构造器。 但是,它可以使用AspectJ为所有aspect定义的静态方法aspectOf()获得一个 aspect的引用,并且,能够把依赖注入aspect。

6.2.1.1. 举例

考虑一个关于安全的aspect,它依赖于一个安全管理对象。这个aspect应用于 Account类中实例变量balance的所有的值变化。(我们不能够以同样方法使 用Spring AOP做到这点。)

AspectJ中aspect的代码(Spring/AspectJ的一个例子),显示如下。注意, 对SecurityManager接口的依赖在Java Bean的属性中说明。

public aspect BalanceChangeSecurityAspect { private 
            SecurityManager securityManager; public void 
            setSecurityManager(SecurityManager securityManager) { 
            this.securityManager = securityManager; } private pointcut 
            balanceChanged() : set(int Account.balance); before() : 
            balanceChanged() { this.securityManager.checkAuthorizedToModify(); 
            } }

我们配置这个aspect的方式和普通类是一样的。注意,我们设置属性引用 的方式是完全相同的。注意,我们必须使用factory-method属性来指定使用 aspectOf()静态方法”创建”这个aspect。实际上,是定位(locating), 而非创建(creating)这个aspect,但Spring容器不关心这些。

<bean id="securityAspect" 
            class="org.springframework.samples.aspectj.bank.BalanceChangeSecurityAspect" 
            factory-method="aspectOf" > <property 
            name="securityManager"> <ref 
            local="securityManager"/> </property> 
            </bean>

我们不需要在Spring配置中做任何事情去定位(target)这个aspect。 在这个aspect的控制适用地方的AspectJ代码里,包含了切入点(pointcut) 的信息。这样它甚至能够适用于不被Spring IoC容器管理的对象。

6.2.1.2. 排序问题

待完成

6.2.2. 非单例aspect

** 按每个目标完成资料,等等。(Complete material on per target etc)

6.2.3. 3.4 转向(Gotchas)

待完成

- 单例问题

6.3. 使用AspectJ切点定位Spring的建议

在Spring将来的版本中,我们计划支持在Spring XML或者其它的Bean定义 文件中使用AspectJ的切入点表达式来定位Spring通知(advice)。这将允许 AspectJ切入点模型的某些能力被应用在Spring基于代理的AOP框架。这将可以在 纯Java中工作,并且不需要AspectJ编译器。仅仅AspectJ切入点相关的方法调用的 子集是可用的。

这个特性计划在Spring 1.2版本中提供,它有赖于AspectJ的增强。

这个特性替代了我们先前为Spring创建一个切入点表达式语言的计划。

6.4. Spring提供给AspectJ的aspect

在将来的Spring版本中(可能是1.2),我们将加入一些Spring的服务作为 AspectJ的aspect,像声明性事务服务。这将允许AspectJ的用户使用这些服务, 而无需潜在地依赖于Spring的AOP框架,甚至,不必依赖Spring IoC容器。

AspectJ的用户可能比Spring用户对这个特性更感兴趣。