上篇文章咱們講到了使用註解的形式來使用Spring AOP。本文咱們介紹如何使用XML Schema的形式使用Spring AOP。java
要想使用本文的AOP命名空間標記,須要導入xmlns:aop="www.springframework.org/schema/aop"。git
在Spring配置中,全部Aspect和Advisor元素都必須放在aop:config元素中(在應用程序上下文配置中能夠有多個aop:config元素)。aop:config元素能夠包含pointcut、advisor和aspect元素(請注意,這些元素必須按該順序聲明)。github
一個aspect是定義在Spring應用程序上下文的java bean對象。spring
你可使用aop:aspect元素聲明一個方面,並使用ref屬性引用相應的bean,以下示例所示:express
<aop:config>
<aop:aspect id="concurrentOperationRetry" ref="concurrentOperationExecutor">
</aop:aspect>
</aop:config>
<bean id="concurrentOperationExecutor" class="com.flydean.aspect.ConcurrentOperationExecutor">
<property name="maxRetries" value="3"/>
<property name="order" value="100"/>
</bean>
複製代碼
你能夠在aop:config中使用aop:pointcut來定義一個Pointcut,以下所示:app
<aop:config>
<aop:pointcut id="idempotentOperation" expression="execution(* com.flydean.service.*.*(..)) and @annotation(com.flydean.beans.Idempotent)"/>
</aop:config>
複製代碼
定義在頂層aop:config中的aop:pointcut能夠在多個aspects和advisors之間共享。ide
當組合切入點子表達式時,可使用and、or和not關鍵字來代替&& || 和!,以下所示:this
<aop:pointcut id="businessService" expression="execution(* com.xyz.myapp.service.*.*(..)) && this(service)"/>
複製代碼
<aop:pointcut id="businessService" expression="execution(* com.xyz.myapp.service.*.*(..)) and this(service)"/>
複製代碼
schema-based AOP 支持使用與@Aspectj樣式相同的五種建議,它們具備徹底相同的語義。spa
Before Advicepwa
在匹配的方法執行以前運行通知。它經過在aop:aspect中聲明使用的aop:before元素,以下示例所示:
<aop:before pointcut-ref="dataAccessOperation" method="doAccessCheck"/>
複製代碼
After Returning Advice
After Returning Advice,在匹配的方法執行正常完成時運行。它在一個aop:aspect中聲明,方式與以前的通知相同。下面的示例演示如何聲明它:
<aop:after-returning pointcut-ref="dataAccessOperation" method="doAccessCheck"/>
複製代碼
正如在@Aspectj樣式中同樣,您能夠在通知正文中得到返回值。爲此,請使用returning來指定應將返回值傳遞到的參數的名稱,以下示例所示:
<aop:after-returning pointcut-ref="dataAccessOperation" returning="retVal" method="doAccessCheck"/>
複製代碼
doAccessCheck方法必需要有聲明名爲retval的參數。以下所示:
public void doAccessCheck(Object retVal) {...
複製代碼
After Throwing Advice
當匹配的方法引起異常退出時執行。它經過在aop:aspect中聲明after-throwing 元素來實現,以下示例所示:
<aop:after-throwing pointcut-ref="dataAccessOperation" method="doRecoveryActions"/>
複製代碼
一樣的,你能夠在通知方法中得到拋出的異常,以下所示:
<aop:after-throwing pointcut-ref="dataAccessOperation" throwing="dataAccessEx" method="doRecoveryActions"/>
複製代碼
doRecoveryActions方法必須有聲明名爲DataAccessEx的參數,以下所示:
public void doRecoveryActions(DataAccessException dataAccessEx) {...
複製代碼
After (Finally) Advice
不管匹配的方法執行如何退出,after(finally)通知都會運行。可使用after元素聲明它,以下示例所示:
<aop:after pointcut-ref="dataAccessOperation" method="doReleaseLock"/>
複製代碼
Around Advice
最後一種advice是around advice的。around通知運行「around」匹配的方法執行。它有機會在方法執行以前和以後都進行工做,並肯定什麼時候、如何以及該方法真正開始執行。
你可使用aop:around元素來聲明around advice。advice方法的第一個參數必須是ProceedingJoinPoint類型。
<aop:around pointcut-ref="businessService" method="doBasicProfiling"/>
複製代碼
doBasicProfiling advice的實現以下:
public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
// start stopwatch
Object retVal = pjp.proceed();
// stop stopwatch
return retVal;
}
複製代碼
若是您但願顯式地爲advice方法指定參數名,可使用advice元素的arg-names屬性來指定參數名,下面是例子:
<aop:config>
<aop:aspect ref="profiler">
<aop:pointcut id="theExecutionOfSomePersonServiceMethod" expression="execution(* com.flydean.service.PersonService.getPerson(String,int)) and args(name, age)"/>
<aop:around pointcut-ref="theExecutionOfSomePersonServiceMethod" method="profile"/>
</aop:aspect>
</aop:config>
複製代碼
相應的aspect bean定義以下:
public class SimpleProfiler {
public Object profile(ProceedingJoinPoint call, String name, int age) throws Throwable {
StopWatch clock = new StopWatch("Profiling for '" + name + "' and '" + age + "'");
try {
clock.start(call.toShortString());
return call.proceed();
} finally {
clock.stop();
System.out.println(clock.prettyPrint());
}
}
}
複製代碼
profile接收兩個參數。
「Advisors」的概念來自於Spring中定義的AOP支持,在AspectJ中沒有直接的等價物。Advisors就像一個獨立的小方面,只有一條advice。
Spring使用aop:advisor元素支持Advisor概念。您一般會看到它與事務性advice結合使用,後者在Spring中也有本身的名稱空間支持。如下示例展現了advisor:
<aop:config>
<aop:pointcut id="businessService" expression="execution(* com.xyz.myapp.service.*.*(..))"/>
<aop:advisor pointcut-ref="businessService" advice-ref="tx-advice"/>
</aop:config>
<tx:advice id="tx-advice">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
複製代碼
本文的例子能夠參考aop2 更多教程請參考 flydean的博客