第 6 章 集成AspectJ
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。
Spring/AspectJ集成最重要的部分是允许Spring的依赖注射来配置AspectJ的aspect。 这给方面(aspect)和对象(object)带来了类似的好处。例如:
-
Aspect不需要使用特定的配置机制;它们可以使用和整个应用相同的、一致的方法来配置。
-
•Aspect可以依赖应用对象。例如,一个权限aspect可以依赖一个权限管理对象,稍后我们可以看到例子。
-
可以通过相关的Spring上下文(Context)获得一个aspect的引用(reference),这可以允许动态的aspect配置。
AspectJ 的方式可以通过设值方式(setter)的注入Java Bean的属性,也可以通过实现Spring的生命周期接口来实现,例如实现 BeanFactoryAware。
值得注意的是,AspectJ不能使用构造器注入方式和方法注入方式, 这是由于aspect没有类似对象的构造器那样可以调用方法的原因。大多数情况下,AspectJ的aspect是单例的,每个类装载器一个实例, 这个单一的实例负责通知(advising)多个对象实例。
Spring IoC容器不能实例化aspect,因为,aspect没有可调用的构造器。 但是,它可以使用AspectJ为所有aspect定义的静态方法aspectOf()获得一个 aspect的引用,并且,能够把依赖注入aspect。
考虑一个关于安全的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容器管理的对象。
在Spring将来的版本中,我们计划支持在Spring XML或者其它的Bean定义 文件中使用AspectJ的切入点表达式来定位Spring通知(advice)。这将允许 AspectJ切入点模型的某些能力被应用在Spring基于代理的AOP框架。这将可以在 纯Java中工作,并且不需要AspectJ编译器。仅仅AspectJ切入点相关的方法调用的 子集是可用的。
这个特性计划在Spring 1.2版本中提供,它有赖于AspectJ的增强。
这个特性替代了我们先前为Spring创建一个切入点表达式语言的计划。