Spring支援使用@AspectJ
注釋樣式方法和基於模式的方法來實現自定義方面。
方面(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
是指將Java方法注釋為Java 5注釋的常規Java類的方式。 @AspectJ
是指將Java方法注釋為Java 5注釋的常規Java類的方式。通過在基於XML Schema的組態檔案中包含以下元素來啟用@AspectJ
支援。
<aop:aspectj-autoproxy/>
方面(aspect
)的類就像任何其他正常的bean一樣,並且可以像任何其他類一樣具有方法和欄位,不過它們使用@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
的組態時,切入點宣告有兩部分:
以下範例定義了一個名為「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(){
...
}