Spring实战(第四版)读书笔记12——在XML中声明切面以及注入AspectJ切面

1、总述

Spring的AOP配置元素能够以非侵入性的方式声明切面。

2、声明前置和后置通知

例子:

<aop:config>
	<aop:aspect ref="audience">
		<aop:pointcut expression="excution(** concert.Performance.perform(..))" id="performance"/>
		<aop:before method="silenceCellPhones" pointcut-ref="performance" />
		<aop:before method="takeSeats" pointcut-ref="performance" />
		<aop:after-returning method="applause" pointcut-ref="performance" />
		<aop:after-throwing method="demandRefund" pointcut-ref="performance" />
	</aop:aspect>	
</aop:config>

3、声明环绕通知

环绕通知相对于前、后置通知的优势:在一个方法内实现,不需要使用成员变量保存状态,如果bean是单例的后者会存在线程安全问题。

例子:

<aop:config>
	<aop:aspect ref="audience">
		<aop:pointcut expression="excution(** concert.Performance.perform(..))" id="performance"/>
		<aop:around method="watchPerformance" pointcut-ref="performance" />
	</aop:aspect>	
</aop:config>

4、为通知传递参数

例子:

<aop:config>
    <aop:aspect ref="trackCounter">
        <aop:pointcut id="trackPlayed" expression="execution(* soundsystem.CompactDisc.playTrack(int) and args(trackNumber))" />
        <aop:before pointcut-ref="trackPlayed" method="countTrack" />
    </aop:aspect>
</aop:config>

5、通过切面引入新功能

例子:

<aop:aspect>
    <aop:declare-parents types-matching="concert.Performance+" implement-interface="concert.Encoreable" defaule-impl="concert.DefaultEncoreable" />
</aop:aspect>
<bean id="encoreableDelegate" class="concert.DefaultEncoreable" />

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

以上是两种标识所引入接口的实现的方式,前者直接使用全限定类名来显式指定Encoreable的实现,后者则引用了一个bean作为引入的委托。显然,后者因为是一个bean,它本身可以被注入、通知或者使用其他Spring配置。

6、注入AspectJ切面

AspectJ提供了更强大的AOP解决方案,并可以和Spring配合使用(如:借助Spring依赖注入把bean装配进AspecJ切面中)。

例子:

<bean class="com.springinaction.springidol.CriticAspect" factory-method="aspectOf">
    <property name="criticismEngine" ref="criticismEngine" />
</bean>

通常情况下,spring bean由spring容器初始化,但是AspectJ切面是由AspectJ在运行期创建的,等到spring要为切面注入时,切面已经被初始化了,因此需要通过使用factory-method来调用aspectOf()方法来获得切面的引用,之后进行依赖注入。