4.4.4 通过切面引入新的功能

在前面的 4.3.4 小节中,我向你展现了如何借助 AspectJ 的 @DeclareParents 注解为被通知的方法神奇地引入新的方法。但是 AOP 引入并不是 AspectJ 特有的。使用 Spring aop 命名空间中的 <aop:declare-parents> 元素,我们可以实现相同的功能。

如下的 XML 代码片段与之前基于 AspectJ 的引入功能是相同:

<aop:aspect>
  <aop:delate-parents
    types-matching="concert.Performance+"
    implement-interface="concert.Encoreable"
    default-impl="concert.DefaultEncoreable" />
</aop:aspect>

顾名思义,<aop:declare-parents> 声明了此切面所通知的 bean 要在它的对象层次结构中拥有新的父类型。具体到本例中,类型匹配 Performance 接口(由 types-matching 属性指定)的那些 bean 在父类结构中会增加 Encoreable 接口(由 implement-interface 属性指定)。最后要解决的问题是 Encoreable 接口中的方法实现要来自于何处。

这里有两种方式标识所引入接口的实现。在本例中,我们使用 default-impl 属性用全限定类名来显式指定 Encoreable 的实现。或者,我们还可以使用 delegate-ref 属性来标识。

<aop:aspect>
  <aop:delate-parents
    types-matching="concert.Performance+"
    implement-interface="concert.Encoreable"
    delegate-ref="encoreableDelegate" />
</aop:aspect>

delegate-ref 属性引用了一个 Spring bean 作为引入的委托。这需要在 Spring 上下文中存在一个 ID 为 encoreableDelegate 的 bean。

<bean id="encoreableDelegate" class="concert.DefaultEncoreable" />

使用 default-impl 来直接标识委托和间接使用 delegate-ref 的区别在于后者是 Spring bean,它本身可以被注入、通知或使用其他的 Spring 配置。

Last updated