javascript
Spring AOP之ThrowsAdvice
目前的項目中接觸了一些Spring的AOP的部分,比如聲明式事務管理。在了解了AOP在Spring的實現之后,的確發現這種新的編程思路確實為我們提供用一種新的思路解決問題的辦法。為了記錄這個學習過程,整理一下學習的筆記。
1.? 幾個重要的概念(詳細的情況參見Spring的在線文檔)
·???????? PointCut:一組JointPoint。在Spring中我們可以通過一些正則表達式定義那些JointPoint組成了我們需要的一個PointCut,從而使我們的Advice可以被編制進來。
·???????? Introduction:Introduction可以我們在已經存在的類中在不修改這個類的情況下增加屬性和方法,從而增加其狀態和動作;
·???????? Target:滿足PointCut定義的條件的一個類,我們可以把Advice用于這個類。大多Spring的AOP是通過動態代理的機制實現的,這個Target就是那個被代理的對象;
·???????? Proxy:為了將一個Advice應用到另外一個類中,比如實現Around Advice,就是在一個方法執行前后加上其他的代碼,那么實際的實現一定是先執行一段Advice的代碼,然后執行Target的那個方法,之后再執行一段Advice的代碼,也就是客戶端執行某個類的時候,實際執行的是一個代理,由代理再把調用傳遞到那個Target中。
·???????? Weaving(編織):有了Target和Advice,在什么時機將這兩個模塊編織在一起呢?可以選擇的方法包括編譯的時候(這樣我們需要一個特殊的編譯器),裝載類的時候(這樣我們需要一個特殊的ClassLoader)和運行的時候(AOP容易可以動態的創建一個代理從而將調用由這個代理傳遞到Target類中)。
2. Throws Advice
目前的項目中有這么一個要求,對于某些處理流程如果在運行的時候拋出了一些異常,需要將這些異常的信息記錄下來,保存在數據庫或發郵件給開發人員。我們切不說這個需求跟TDD有什么沖突的地方,先看看如何實現吧。
按照上面概念的描述,我們應該主要注意三個概念:Target,Advice和Proxy。
2.1 Target的實現
Target就是上面所說的業務流程類,我們按照正常的開發編寫代碼即可,沒有什么特殊的要求。如:
public interface IBizProcess
{
??????????????? void doOneThing();
?????????????? void doAnotherThing();
}
public class BizProcessImpl implements IBizProcess
{
??????????????? public void doOneThing()
{
}
public void doAnotherThing()
{
??????????????? throw new RuntimeException( “Boom” );
}
}
2.2 Advice
為了實現當業務流程拋出異常時的Advice,我們需要定義個一個Advice類,實現ThrowsAdvice接口。這個接口里面沒有定義方法,我們要求我們的類必須實現afterThrows這個方法,如下:
public void afterThrows( [Method method,] [Object args,] [Object target,] Throwable throwable );
這個方法的前面三個參數都是可選的。我們在同一個類中定義這個方法的多個版本,如:
public void afterThrowing( MyException1 ex ) {}
public void afterThrowing( MyException2 ex ) {}
具體那個方法被調用則根據具體的Exception來判斷,由AOP容易自動識別執行。
2.3 Proxy(代理)
Spring中一個簡單的實現是用它的org.springframework.aop.framework.ProxyFactoryBean。這個Bean包含了很多個屬性,其中有三個我們需要設置:target,proxyInterfaces和interceptorNames,如下:
<bean id=”bizOneTarget” class=”com.company.biz.impl.BizProcessImpl”/>
<bean id=”throwsAdvice” class=”com.company.advice.MyThrowsAdvice”/>
<bean id=”bizOne” class=”org.springframework.aop.framework.ProxyFactoryBean”>
??????????? <property name=”target”><ref bean=”bizOneTargte”/></property>
??????????? <property name=”proxyInterfaces”>
??????????????????????? <value>com.company.biz.IBizProcessImpl</value>
??????????? </property>
??????????? <property name=”interceptorNames”>
??????????????????????? <list>
??????????????????????????????????? <value>throwsAdvice</value>
??????????????????????? </list>
??????????? </property>
</bean>
通過上面的配置,Spring就把Target和Advice編織在了一起。需要說明的是,proxyInterfaces和interceptorNames都可以是多個,如果是多個的話就需要用list來定義。interceptorNames的先后次序決定了這些Advice執行的先后次序。
3. 簡化配置
從上面的例子可以看出,如果有多個BizProcess的對象需要代理,我們在Spring配置中為每一個Bean都配置一個代理,那么配置文件的維護就成了麻煩。為此,Spring提供了比較方便的方法解決這個問題,比如BeanNameAutoProxyCreator、DefaultAdviceAutoProxyCreator和metadata autoproxying。我們采用了BeanNameAutoProxyCreator,因為他比較直觀和簡單。
配置如下:
<bean id=”beanNameAutoProxyCreator” class=”org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator”>
??????????? <property name=’beanNames”>
??????????????????????? <list>
??????????????????????????????????? <value>*Service</value>
??????????????????????? </list>
??????????? </property>
??????????? <property name=”interceptorNames”>
??????????????????????? <value>throwsAdvice</value>
??????????? </property>
</bean>
從中我們可以看到,所有以Service結尾的bean都會由Spring自動創建代理,從而實現Advice的織入。
總結
以上是生活随笔為你收集整理的Spring AOP之ThrowsAdvice的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最近看的电影(乱谈)
- 下一篇: 有关C++多态的一些测试