1.4.2 AOP使用
假设你将你的进展展示给市场部以后,他们增加了新的需求。新的需求是,每个骑士都要有一个吟游诗人陪伴,用歌曲来记载骑士的行动和功绩。
首先,我们创建一个Minstrel类,如程序清单1.10所示:
程序清单1.10 A Minstrel——一个音乐日志组件
|
|
有个问题,就是每个骑士在继续探险之前,必须停下来吩咐吟游诗人谱一首曲子(见图1.9)。在探险之后,骑士必需记得告诉歌手继续歌颂他的探险。必需记得要停下来并告诉歌手做什么,这当然会耽误骑士的探险。
理想状态下,歌手应该不等通知就谱写曲子。骑士不应该知道(甚至不关心)他的行动被记录到歌曲中了。毕竟,你不能因为一个懒惰的歌手而耽误了探险。
简单地说,吟游诗人提供的服务超出了骑士的责任。也就是说,吟游诗人的工作(写歌)与骑士的职责(探险)交叉在一起了。所以,把吟游诗人实现成切面,并把他的写歌服务提供给骑士是合理的。然后,吟游诗人的服务包含了骑士的功能。骑士甚至都无需知道吟游诗人在旁边,如图1.10所示。
|
|
也就是说,简单的方法就是使用Spring的AOP支持将程序清单1.10中的Minstrel类转换成一个切面。下面让我们看看如何实现的。
编织切面
在Spring中有多种方面可以用来实现切面,第4章中将详细介绍该内容。但是为了这个例子,我们将使用新的AOP命名空间(Spring 2.0新引入的)。首先必需确保在上下文定义XML中申明命名空间:
|
|
在程序清单1.11中有很多内容,因此我们将分别介绍:
我们所看到的第一个事情是<bean>声明,在Spring中创建一个minstrel bean。这个Minstrel类来自程序清单1.10。Minstrel没有任何依赖,因此没有必要注入任何东西。
下一个是<aop:config>元素。这个元素表示我们将做一些AOP工作。多数Spring的AOP配置元素必需包含在<aop:config>中。
在<aop:config>中,有一个<aop:aspect>元素。这个元素表示我们正在声明一个切面。切面的功能性在ref属性引用的bean中定义。在这里,minstrel bean提供了该切面的功能。
切面有切入点(切入点是指应用切面功能的位置)组成和方法(如何应用功能)。<aop:pointcut>元素定义了切入点,执行embarkOnQuest()方法即可触发该切入点。
最后,有两个AOP通知。<aop:before>`元素声明Minstrel的singBefore()方法应该在切入点之前调用,而<aop:after>元素声明Minstrel的singAfter()方法应该在切入点之后调用。此时,切入点都是对questPointcut的引用,它执行embarkOnQuest()。
这是全部内容!我们已经将Minstrel转换成了Spring切面。如果此时还没有完全理解,不必担心,在第4章中,我们将深入讨论更多的Spring AOP的例子。现在,从这个例子中,我们必需掌握两个重点。
首先,Mistrel仍然是一个POJO——表示它可以被用作为一个切面。Minstrel在Spring上下文中被显示地转换成一个切面。
其次,更为重要的是,骑士不再需要告诉诗人来歌颂其探险。作为一个切面,诗人自动处理歌颂事项。实际上,骑士甚至无需知道诗人的存在。结果是,KnightOfTheRoundTable类可以恢复到一个更简单的形式:
![]() |
| 回书目 上一节 下一节 |