熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

淺析Spring.net中的Aop使用

2013-11-23 20:08:47  來源: Java開源技術 
    一 什麼是AOP
   
    AOP為Aspect Oriented Programming的縮寫意為面向切面編程(也叫面向方面)可以通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加 功能的一種技術AOP實際是GoF設計模式的延續設計模式孜孜不倦追求的是調用者和被調用者之間的解耦AOP可以說也是這種目標的一種實現
   
    主要的功能是日志記錄性能統計安全控制事務處理異常處理等等
   
    主要的意圖是將日志記錄性能統計安全控制事務處理異常處理等代碼從業務邏輯代碼中劃分出來通過對這些行為的分離我們希望可以將它們獨立到非指導業務邏輯的方法中進而改變這些行為的時候不影響業務邏輯的代碼
   
    可以通過預編譯方式和運行期動態代理實現在不修改源代碼的情況下給程序動態統一添加功能的一種技術AOP實際是GoF設計模式的延續設計模式孜孜不倦追求的是調用者和被調用者之間的解耦AOP可以說也是這種目標的一種實現
   
    在Spring中提供了面向切面編程的豐富支持允許通過分離應用的業務邏輯與系統級服務(例 如審計(auditing)和事務(transaction)管理)進行內聚性的開發應用對象只實現它們應該做的完成業務邏輯僅此而已它們並 不負責(甚至是意識)其它的系統級關注點例如日志或事務支持
   

  

 
                                                                              切面(Aspect)
   
    切面是你要實現的交叉功能它是應用系統模塊化的一個切面或領域切面的最常見(雖然簡單)例子是日志記錄日志記錄在系統中到處需要用到利用繼承來重用日志模塊不適合然而你可以創建一個日志記錄切面並且使用AOP在系統中應用
   
    連接點(Joinpoint)
   
    連接點是應用程序執行過程中插入切面的地點這個地點可以是方法調用異常拋出或者甚至是要修改的字段切面代碼在這些地方插入到你的應用流程中添加新的行為
   
    通知(Advice)
   
    通知切面的實際實現它通知應用系統新的行為在日志例子中日志通知包含了實現實際日志功能的代碼如向日志文件寫日志通知在連接點插入到應用系統中
   
    切入點(Pointcut)
   
    切入點定義了通知應該應用在哪些連接點通知可以應用到AOP框架支持的任何連接點當然你並不希望把所有切面應用到所有可能的連接點上切入點讓你指定通知應用到什麼地方通常通過指定類名和方法名或者匹配類名和方法名式樣的正則表達式來指定切入點一些AOP框架允許動態創建切入點在運行時根據條件決定是否應用切面如方法參數值
   
    引入(Introduction)
   
    引入允許你為已存在類添加新方法和屬性例如你可以創建一個稽查通知來記錄對象的最後修改時間只要用一個方法setLastMofified(Date)以及一個保存這個狀態的變量可以在不改變已存在類的情況下將這個引入給他們新的行為和狀態
   
    目標對象(Target)
   
    目標對象是被通知對象它既可以是你編寫的類也可以是你要添加制定行為的第三方類如果沒有AOP這個類就必須要包含它的主要邏輯以及其他交叉業務邏輯有了AOP目標對象就可以全身心地關注主要業務忘記應用其上的通知
   
    代理(Proxy)
   
    代理是將通知應用到目標對象後創建的對象對於客戶對象來說目標對象(應用AOP之前的對象)和代理對象(應用AOP之後的對象)是一樣的也就是應用系統的其他部分不用為了支持代理對象而改變
   
    織入 (Weaving)
   
    織入是將切面應用到目標對象從而創建一個新的代理對象的過程切面在指定接入點被織入到目標對象中
   
    二 幾個重要接口
   
    用於找到用於通知的相關的類型和方法
   
    View Code
   
    public interface IPointcut
   
    {
   
    ITypeFilter TypeFilter { get; }
   
    IMethodMatcher MethodMatcher { get; }
   
    }
   
    用於匹配相關類型
   
    View Code
   
    public interface ITypeFilter
   
    {
   
    bool Matches(Type type)
   
    }
   
    public interface IMethodMatcher
   
    {
   
    bool IsRuntime { get; }
   
    bool Matches(MethodInfo method Type targetType)
   
    bool Matches(MethodInfo method Type targetType object[] args)
   
    } Matches(MethodInfo Type)
   
    方法用來測試這個切入點是否匹配目標類的指定方法這將在AOP代理被創建的時候執行這樣可以避免在每次方法調用的時候都執行如果兩個參數的matches方法對於一個給定的方法返回true並且IMethodMatcher接口的IsRuntime方法也返回true那麼有三個參數的matches方法將在每個方法調用時被調用 這使得切入點在通知將被執行前可以查看傳入到方法的參數
   
    絕大多數的IMethodMatcher接口是static的這也就意味著它們的IsRuntime屬性返回false在這種情況下有三個參數的Matches方法將永遠不會被調用
   
    三 通知
   
    通知生命周期
   
    通知類型
   
    一攔截環繞通知(around advice)SpringNET中最基本的通知類型是攔截環繞通知(interception around advice)即方法攔截器攔截環繞通知繼承IMethodInterceptor接口注意其中IMethodInvocationProceed()方法的調用該方法會依次調用攔截器鏈上的其它攔截器大部分攔截器都需要調用這個方法並返回它的返回值當然也可以不調用Proceed方法而返回一個其它值或拋出一個異常但一般不太會這麼做
   
    二前置通知(before advise)是在IMethodInterceptorProceed()方法調用前的通知繼承自IMethodBeforeAdvice接口
   
    三異常通知(throws advise)是在IMethodInterceptorProceed()方法調用時發生異常的通知繼承自IthrowsAdvice接口IthrowsAdvice接口沒有定義任何方法它是一個標識接口(按之所以用標識接口原因有二在通知方法中只有最後一個參數是必須的如果聲明為接口的方法參數列表就被固定了如果第一個原因可以用重載的接口方法解決那麼這個原因就是使用標識接口的充分原因了實現此接口的類必須聲明一或多個通知方法接口方法做不到這一點)用以表明實現它的類聲明了一或多個強類型的異常通知方法
   
    四後置通知(after returning advise)是在IMethodInterceptorProceed()方法調用後的通知繼承自IAfterReturningAdvice接口後置通知對切入點的執行沒有影響如果通知拋出異常就會沿攔截器鏈向上拋出從而中斷攔截器鏈的繼續執行
   
    Interception Around Advice(環繞攔截通知後面的講解以環繞攔截通知為例子)
   
    方法攔截器接口
   
    View Code
   
    public interface IMethodInterceptor : IInterceptor
   
    {
   
    object Invoke(IMethodInvocation invocation)
   
    }


    
    模擬環繞攔截通知
   
    View Code
   
    public class DebugInterceptor : IMethodInterceptor
   
    {
   
    public object Invoke(IMethodInvocation invocation)
   
    {
   
    ConsoleWriteLine(Before: invocation=[{}] invocation)
   
    object rval = invocationProceed()
   
    ConsoleWriteLine(Invocation returned
   
    return rval;
   
    }
   
    }
   
    注意 IMethodInvocation 的 Proceed 方法proceed方法返回方法的返回值
   
    四 切入點操作
   
    靜態切入點
   
    ProxyFactoryObject 顯式創建AOP代理
   
    AOP 配置文件
   
    <object id=UserValidateTarget type=StephenSpringNetAOPSampleServciesImplUserValidate Servcies></object>
   
    <object id=RoundInterceptor type=StephenSpringNetAOPSampleServciesInterceptorRoundInterceptor Servcies></object>
   
    <object id=UserValidateProxy type=SpringAopFrameworkProxyFactoryObject SpringAop>
   
    <property name=proxyInterfaces value=StephenSpringNetAOPSampleServciesIValidateService/>
   
    <property name=target ref=UserValidateTarget/>
   
    <property name=interceptorNames>
   
    <list>
   
    <value>RoundInterceptor</value>
   
    </list>
   
    </property>
   
    </object>
   
    不過由於顯式的創建AOP在要創建多個代理的時候需要重復的配置因此Spring提供了自動代理
   
    ObjectNameAutoProxyCreator 對象名稱自動切入點
   
    可以用特定的文本值或通配符匹配目標對象的名稱並為滿足條件的目標對象創建AOP代理該類支持模式匹配字符串*namename**name*和精確文本如name我們可以通過下面這個簡單的例子了解一下自動代理的功能
   
    AOP 配置文件
   
    <object id=IValidateProxy type=SpringAopFrameworkAutoProxyObjectNameAutoProxyCreator SpringAop>
   
    <property name=ObjectNames>
   
    <list>
   
    <value>*Validate</value>
   
    </list>
   
    </property>
   
    <property name=InterceptorNames value=RoundInterceptor></property>
   
    </object> 測試方法
   
    [TestMethod]
   
    public  void ObjectNameAutoProxyCreatorMethodTest()
   
    {
   
    var context = ContextRegistryGetContext()
   
    IDictionary validates = contextGetObjectsOfType(typeof(IValidateService))
   
    foreach (DictionaryEntry validate in validates)
   
    {
   
    ((IValidateService) validateValue)Validate(null)
   
    }
   
    }
   
    執行結果
   
    ObjectNameAutoProxyCreatorMethodTest : Passed
   
    Method:Validate開始執行
   
    Method:Validate執行完畢
   
    SdkRegularExpressionMethodPointcut 通過正則表達式來匹配需要執行的類或方法
   
    AOP 配置
   
    <object id=ValidatePointCut type=SpringAopSupportSdkRegularExpressionMethodPointcut SpringAop>
   
    <property name=Pattern value=UserValidateAdvance*></property>
   
    </object>
   
    <aop:config>
   
    <aop:advisor adviceref=RoundInterceptor pointcutref=ValidatePointCut/>
   
    </aop:config> pattern 的屬性 UserValidateAdvance* 表示 匹配 UserValidate 類中的以Advance開頭的方法
   
    DefaultAdvisorAutoProxyCreator+RegularExpressionMethodPointcutAdvisor 創建正則表達式AOP
   
    AOP 配置
   
    <object id=ProxyCreator type=SpringAopFrameworkAutoProxyDefaultAdvisorAutoProxyCreator SpringAop/>
   
    <object id=ValidateRegularExpressionPointCut type=SpringAopSupportRegularExpressionMethodPointcutAdvisor SpringAop>
   
    <property name=advice ref=RoundInterceptor/>
   
    <property name=patterns>
   
    <list>
   
    <value>UserValidateAdvance*</value>
   
    </list>
   
    </property>
   
    </object>
   
    特性Aop
   
    可以通過Attribute類來實現AOP
   
    [AttributeUsage(AttributeTargetsMethod)]
   
    public class AopAttribute:Attribute
   
    {
   
    } AOP 配置
   
    <object id=aroundAdvisor type=SpringAopSupportAttributeMatchMethodPointcutAdvisor SpringAop>
   
    <property name=Advice ref=RoundInterceptor/>
   
    <property name=Attribute
   
    value =StephenSpringNetAOPSampleServciesAopAttribute Servcies />
   
    </object>
   
    <object id=ValidateAttributeProxy type=SpringAopFrameworkProxyFactoryObject SpringAop>
   
    <property name=proxyInterfaces value=StephenSpringNetAOPSampleServciesIValidateService/>
   
    <property name=target ref=UserValidateTarget/>
   
    <property name=interceptorNames>
   
    <list>
   
    <value>aroundAdvisor</value>
   
    </list>
   
    </property>
   
    </object>


From:http://tw.wingwit.com/Article/program/Java/ky/201311/28013.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.