瘋狂

          STANDING ON THE SHOULDERS OF GIANTS
          posts - 481, comments - 486, trackbacks - 0, articles - 1
            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

          通過(guò)Annotation來(lái)實(shí)現(xiàn)AOP(轉(zhuǎn))

          Posted on 2008-10-20 12:45 瘋狂 閱讀(2071) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): java
          文章來(lái)源:http://jummy.javaeye.com/blog/255126,thank u,jummy。
           

          首先寫(xiě)個(gè)題記吧 --- 如果你是 Spring 高手。那么我所寫(xiě)的文章對(duì)你可能一文不值 ( 至少最近幾篇 ) ,就等于說(shuō)讓你看小學(xué)課本 ( 本人水平也一般 ) ;如果你覺(jué)得你是個(gè)新手,希望這篇文章沒(méi)有浪費(fèi)你的時(shí)間,讓你有所收獲!

          前兩篇文章一直不斷的在給 Spring AOP 做鋪墊。如果你剛接觸 AOP 不久還是希望你從 JDK 動(dòng)態(tài)代理那篇文章一一看起,那也是我學(xué)習(xí) AOP 的一個(gè)縮影。我覺(jué)得今天該寫(xiě)寫(xiě)所謂 Spring 中的 AOP 了,其實(shí)這并不是個(gè)什么新鮮事物只是 Spring 將它納入自己的框架取名曰: AOP( 面向切面編程 )

          Spring AOP 有兩種實(shí)現(xiàn)技術(shù):一種不太用的是通過(guò) Annotation( 注解 ) 實(shí)現(xiàn)。另一種方法就是通過(guò)配置文件來(lái)實(shí)現(xiàn)也就是我們的 configuration ,通過(guò)配置達(dá)到目的。 ( 這也是現(xiàn)在提倡的用法 ) 。但是為了理解原理,我還是從 Annotation 說(shuō)起吧。懂了原理其他就好辦了。

          Annotation 方式實(shí)現(xiàn) AOP ,首先得添加架包支持這兩個(gè)包就是: aspectjrt.jar aspectjweave.jar 。當(dāng)然你還得添加一些其他的 Spring 支持。我們通過(guò)代碼來(lái)來(lái)講解吧

          因?yàn)槭敲嫦蚯忻婢幊塘耍侵罊M切關(guān)注點(diǎn)了(假如我要實(shí)現(xiàn)安全驗(yàn)證),那我們得將其抽取出來(lái),模塊成一個(gè)類(lèi)(也就是 AOP 的關(guān)鍵工作尋找切面 ,或者說(shuō)自己創(chuàng)建切面 。這個(gè)是可以按需所求的,就是說(shuō)你可以設(shè)計(jì)自己需要功能的切面)。那我就創(chuàng)建一個(gè)安全類(lèi)吧:但為了體現(xiàn)面向接口編程的思想,我們想抽取成接口然后在通過(guò)接口的實(shí)現(xiàn)類(lèi)來(lái)實(shí)現(xiàn)這一功能:

          創(chuàng)建接口:(這個(gè)是普通類(lèi)的接口,也就是后面要使用切面的目標(biāo)類(lèi)的類(lèi)接口)        

           
          1. package com.jummy.aop;   
          2.   
          3. public interface UserManager {   
          4.  public void  addUser(String string,String name);   
          5.  public void delUser(int id);   
          6.  public void modifyUser(int id,String name,int age);   
          7. }  
           

                     

          接著是接口的實(shí)現(xiàn)類(lèi): ( 截圖比較模糊 ,我附有源碼的 )

           
          1. package com.jummy.aop;   
          2. public class UserManagerImpl implements UserManager {   
          3.   
          4.     public void addUser(String id, String name) {   
          5.        
          6.         System.out.println("---UsreManagerImpl中的addUser方法的實(shí)現(xiàn)-----");   
          7.     }   
          8.   
          9.     public void delUser(int id) {   
          10.         System.out.println("-----delUser方法的實(shí)現(xiàn)-----");   
          11.     }   
          12.   
          13.     public void modifyUser(int id, String name, int age) {   
          14.         System.out.println("----modifyUser方法的實(shí)現(xiàn)-----");   
          15.     }   
          16.   
          17. }  
           

           

          創(chuàng)建切面的接口:(所有的切面都可以從此接口繼承,這里這樣寫(xiě)主要是體現(xiàn)面向接口編程的思想。這里提供實(shí)現(xiàn)安全驗(yàn)證的接口)

                 

           
          1. package com.jummy.aop;   
          2.   
          3. public interface MySecurityManager {   
          4.     public void security();   
          5.     //也可以添加多個(gè)方法   
          6.     //public void security2();   
          7. }  
           

           

          創(chuàng)建切面 ( 類(lèi) ) :這是重點(diǎn),除了實(shí)現(xiàn)接口中的方法以外,還需要在 Aspect 中定義 Pointcut 以及 Advice 。當(dāng)然這一切是通過(guò)文章開(kāi)頭說(shuō)的 Aspectj 實(shí)現(xiàn)的,主要功能有兩個(gè)架包提供我們可直接引用( aspectjrt.jar aspectjweave.jar )!

           
          1. import org.aspectj.lang.annotation.Aspect;   
          2. import org.aspectj.lang.annotation.Before;   
          3. import org.aspectj.lang.annotation.Pointcut;   
          4. /*  
          5.  * 我們已經(jīng)把橫切關(guān)注點(diǎn)抽取出來(lái)了  
          6.  * 那就需要定義我們的Aspect了(類(lèi))  
          7.  */  
          8. @Aspect  
          9. //使用@Aspect之前記得要引入aspectjrt.jar和aspectjweaver.jar   
          10. public class MySecurityManagerImpl implements MySecurityManager {   
          11.   
          12.     /*  
          13.      * 定義切入點(diǎn),切入  
          14.      *   
          15.      * 該方法只是一個(gè)標(biāo)識(shí)(而且只作為標(biāo)識(shí)并不是常態(tài)下的方法,并不供人調(diào)用所以沒(méi)有返回值最好設(shè)置為private), 切入點(diǎn)的內(nèi)容是一個(gè)表達(dá)式。  
          16.      * 根據(jù)這個(gè)表達(dá)式就可以用來(lái)判斷切入哪些對(duì)象的哪些方法  
          17.      */  
          18.     @Pointcut("execution(* add*(..))")   
          19.     /*  
          20.      * 下面對(duì)表達(dá)式簡(jiǎn)單說(shuō)一下: execution(* add*(..))第一個(gè)*說(shuō)匹配是方法的任意返回值類(lèi)型       
          21.      * 待會(huì)可以試驗(yàn)一下。add*就是表示以add開(kāi)頭的方法名都可以匹配想到正則表達(dá)式了嗎? (..)這兩個(gè)就是表示方法里所傳遞的參數(shù)類(lèi)型也是任意匹配。  
          22.      * 具體的請(qǐng)參考spring的開(kāi)發(fā)手冊(cè), 這一點(diǎn)Spring講的比較清楚。  
          23.      *   
          24.      */  
          25.     private void addAllMethod() {   
          26.     }   
          27.   
          28.     /*  
          29.      * 定義Advice,標(biāo)識(shí)在哪些切入點(diǎn)(切入點(diǎn)有ADD這是我們上面通過(guò)pointcut定義的。當(dāng)然你也可以定義別的)  
          30.      * 的何處(何處就是指是切入點(diǎn)的前面呢?后面?還是其他情況)織入通知 當(dāng)然除了before還有其他類(lèi)型的通知。這里就不在累贅了  
          31.      *   
          32.      */  
          33.     @Before("addAllMethod()")   
          34.     public void security() {   
          35.         System.out.println("-----調(diào)用security方法-------");   
          36.     }   
          37.     /*這里也可以添加一些其他的前置方法  
          38.      * @Before("addAllMethod()")  
          39.     public void security2() {  
          40.         System.out.println("-----調(diào)用security方法2-------");  
          41.     }  
          42. */  
          43. }  
           

          所有原理我都注釋在源碼中。其中在 Aspect 中需要做的就是定義 Pointcut 以及 Advice 。在定義 Pointcut 的過(guò)程中我們需要注意幾點(diǎn):首先在 Aspectj 的支持下, @Pointcut(“execution(* add*(..))”) 來(lái)實(shí)現(xiàn)。表達(dá)式我不多講了自己看 Spring 的手冊(cè)去吧。解釋代碼中 private void addAllMethod(){} 這是一個(gè)沒(méi)有返回值的空方法體,它程序的實(shí)際運(yùn)行過(guò)程中并不執(zhí)行 ( 同時(shí)我們也不希望它被其他人調(diào)用所以設(shè)置為 private 以權(quán)限控制 ) 。它只是一個(gè)標(biāo)識(shí),這個(gè)標(biāo)識(shí)會(huì)被下面代碼中的 Advice( 也就是 @before(“addAllMethod()”) 調(diào)用。它的作用類(lèi)似于變量名,起一個(gè)被調(diào)用的載體的作用 ( 所以稱(chēng)為標(biāo)識(shí) ) ;當(dāng)然切入點(diǎn)的內(nèi)容 ( 也就是引號(hào)里的一些表達(dá)式 ) 它們起到的作用就是來(lái)描述我們要切入哪些對(duì)象的哪些方法。

            OK pointcut 我們定義完成輪到 Advice 了。 Advice 是通過(guò) @before(“addAllMethod()”) 來(lái)定義的,當(dāng)然你可以是 after/throws 等等其他類(lèi)型的通知。代碼 public void security(){-------}

          這就是通知的具體方法實(shí)現(xiàn),也就是我前面說(shuō)的要添加的安全驗(yàn)證。而且我申明了該驗(yàn)證在我執(zhí)行所有的以 add 開(kāi)頭的方法之前執(zhí)行。

             最后看看 spring 的配置文件里怎么寫(xiě)吧。

          < aop:aspectj-autoproxy /> // 這里就是申明添加 aspectj 的支持,跟導(dǎo)入一個(gè)包類(lèi)似的作用

          <!— 下面是切面的注入 -->

            < bean id = "mySecurityManagerImpl" class = "com.jummy.aop.MySecurityManagerImpl" ></ bean >

            <!-- 這是目標(biāo)對(duì)象的注入 -->

            < bean id = "userManagerImpl" class = "com.jummy.aop.UserManagerImpl" ></ bean >         

          大家可能看到了,通過(guò) Aspectj 對(duì) Annotation 支持實(shí)現(xiàn) , 所有的 Advice Pointcut 啊都是直接在代碼中實(shí)現(xiàn)的 當(dāng)然里面具體邏輯是 Spring 幫你通過(guò)代理來(lái)實(shí)現(xiàn)的,畢竟你自己的實(shí)現(xiàn)類(lèi)中(如 UserManagerImpl 類(lèi)中并沒(méi)有任何對(duì)安全性檢查的調(diào)用)

            

          主站蜘蛛池模板: 剑阁县| 长宁区| 安溪县| 新巴尔虎左旗| 荃湾区| 佳木斯市| 乌什县| 博罗县| 通州区| 榆林市| 舒兰市| 昌邑市| 科尔| 博罗县| 琼结县| 从江县| 修文县| 黔西县| 革吉县| 得荣县| 鄢陵县| 江北区| 社旗县| 阿拉善右旗| 云南省| 濮阳市| 永康市| 萨迦县| 郧西县| 乌兰县| 大冶市| 宜兰市| 松阳县| 堆龙德庆县| 茌平县| 荔波县| 周至县| 洛浦县| 佛教| 东宁县| 新安县|