Spring支持使用@AspectJ
注釋樣式方法和基于模式的方法來實現(xiàn)自定義方面。
方面(Aspects
)使用常規(guī)類以及基于XML的配置來實現(xiàn)。
要使用本節(jié)中描述的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
)有助于確定要用不同建議執(zhí)行的關聯(lián)點(即方法)。 在使用基于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()
方法的執(zhí)行:
<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>
內(nèi)的五個通知中的任何一個聲明如下:
<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注釋的常規(guī)Java類的方式。 @AspectJ
是指將Java方法注釋為Java 5注釋的常規(guī)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
)有助于確定要用不同通知執(zhí)行的關聯(lián)點(即方法)。 在使用基于@AspectJ
的配置時,切入點聲明有兩部分:
以下示例定義了一個名為“businessService
”的切入點,該切入點將匹配com.xyz.myapp.service
包下的類中可用的每個方法的執(zhí)行:
import org.aspectj.lang.annotation.Pointcut;
@Pointcut("execution(* com.xyz.myapp.service.*.*(..))") // expression
private void businessService() {} // signature
以下示例定義了一個名為“getname
”的切入點,該切入點將與com.yiibai
包下的Student
類中的getName()
方法的執(zhí)行相匹配:
import org.aspectj.lang.annotation.Pointcut;
@Pointcut("execution(* com.yiibai.Student.getName(..))")
private void getname() {}
您可以使用@{ADVICE-NAME}
注釋在以下所述的五個建議中聲明任何一個。假設您已經(jīng)定義了一個切入點簽名方法為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(){
...
}
可以為任何通知定義切入點內(nèi)嵌。 下面是一個為之前通知定義的內(nèi)聯(lián)切入點的示例:
@Before("execution(* com.xyz.myapp.service.*.*(..))")
public doBeforeTask(){
...
}