Spring AOP實現
Spring支持使用[@AspectJ](https://github.com/AspectJ "@AspectJ")
註釋樣式方法和基於模式的方法來實現自定義方面。
基於XML模式
方面(Aspects
)使用常規類以及基於XML的配置來實現。
要使用本節中描述的aop
命名空間標籤,您需要按照以下所述導入spring-aop
模式:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
<!-- bean definition & AOP specific configuration -->
</beans>
聲明一個方面(Aspects
)
使用<aop:aspect>
元素聲明一個方面(Aspects
),並使用ref
屬性引用後臺bean
,如下所示:
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
...
</aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>
這個「aBean
」將被配置和依賴注入就像任何其他的Spring Bean
一樣,就像在前幾章中看到的一樣。
聲明一個切入點
切入點(pointcut
)有助於確定要用不同建議執行的關聯點(即方法)。 在使用基於XML模式的配置時,切入點將定義如下:
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..))"/>
...
</aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>
以下示例定義了一個名爲「businessService
」的切入點,該切入點將匹配com.yiibai
包中Student
類中的getName()
方法的執行:
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
<aop:pointcut id="businessService"
expression="execution(* com.yiibai.Student.getName(..))"/>
...
</aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>
聲明通知
您可以使用<aop:{ADVICE NAME}>
元素在<aop:aspect>
內的五個通知中的任何一個聲明如下:
<aop:config>
<aop:aspect id="myAspect" ref="aBean">
<aop:pointcut id="businessService"
expression="execution(* com.xyz.myapp.service.*.*(..))"/>
<!-- a before advice definition -->
<aop:before pointcut-ref="businessService"
method="doRequiredTask"/>
<!-- an after advice definition -->
<aop:after pointcut-ref="businessService"
method="doRequiredTask"/>
<!-- an after-returning advice definition -->
<!--The doRequiredTask method must have parameter named retVal -->
<aop:after-returning pointcut-ref="businessService"
returning="retVal"
method="doRequiredTask"/>
<!-- an after-throwing advice definition -->
<!--The doRequiredTask method must have parameter named ex -->
<aop:after-throwing pointcut-ref="businessService"
throwing="ex"
method="doRequiredTask"/>
<!-- an around advice definition -->
<aop:around pointcut-ref="businessService"
method="doRequiredTask"/>
...
</aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>
可以對不同的通知使用相同doRequiredTask
或不同的方法。 這些方法將被定義爲方面模塊的一部分。
基於@AspectJ
[@AspectJ](https://github.com/AspectJ "@AspectJ")
是指將Java方法註釋爲Java 5註釋的常規Java類的方式。 [@AspectJ](https://github.com/AspectJ "@AspectJ")
是指將Java方法註釋爲Java 5註釋的常規Java類的方式。通過在基於XML Schema的配置文件中包含以下元素來啓用[@AspectJ](https://github.com/AspectJ "@AspectJ")
支持。
<aop:aspectj-autoproxy/>
聲明一個方面(aspect)
方面(aspect
)的類就像任何其他正常的bean一樣,並且可以像任何其他類一樣具有方法和字段,不過它們使用[@Aspect](https://github.com/Aspect "@Aspect")
進行註釋,如下所示:
package org.xyz;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class AspectModule {
}
它們就像任何其他以XML格式配置的bean
一樣,如下所示:
<bean id="myAspect" class="org.xyz.AspectModule">
<!-- configure properties of aspect here as normal -->
</bean>
聲明一個切入點
切入點(pointcut
)有助於確定要用不同通知執行的關聯點(即方法)。 在使用基於[@AspectJ](https://github.com/AspectJ "@AspectJ")
的配置時,切入點聲明有兩部分:
- 一個切入點表達式,確定哪些方法執行。
- 切入點簽名包括名稱和任意數量的參數。 該方法的實體是無關緊要的,也可以是空的。
以下示例定義了一個名爲「businessService
」的切入點,該切入點將匹配com.xyz.myapp.service
包下的類中可用的每個方法的執行:
import org.aspectj.lang.annotation.Pointcut;
@Pointcut("execution(* com.xyz.myapp.service.*.*(..))") // expression
private void businessService() {} // signature
以下示例定義了一個名爲「getname
」的切入點,該切入點將與com.yiibai
包下的Student
類中的getName()
方法的執行相匹配:
import org.aspectj.lang.annotation.Pointcut;
@Pointcut("execution(* com.yiibai.Student.getName(..))")
private void getname() {}
聲明通知
您可以使用@{ADVICE-NAME}
註釋在以下所述的五個建議中聲明任何一個。假設您已經定義了一個切入點簽名方法爲businessService()
,參考以下配置:
@Before("businessService()")
public void doBeforeTask(){
...
}
@After("businessService()")
public void doAfterTask(){
...
}
@AfterReturning(pointcut = "businessService()", returning="retVal")
public void doAfterReturnningTask(Object retVal){
// you can intercept retVal here.
...
}
@AfterThrowing(pointcut = "businessService()", throwing="ex")
public void doAfterThrowingTask(Exception ex){
// you can intercept thrown exception here.
...
}
@Around("businessService()")
public void doAroundTask(){
...
}
可以爲任何通知定義切入點內嵌。 下面是一個爲之前通知定義的內聯切入點的示例:
@Before("execution(* com.xyz.myapp.service.*.*(..))")
public doBeforeTask(){
...
}