<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Junky's IT Notebook

    統(tǒng)計

    留言簿(8)

    積分與排名

    WebSphere Studio

    閱讀排行榜

    評論排行榜

    Spring interceptor

    1 Spring的通知類型

    現(xiàn)在讓我們看看Spring AOP是如何處理通知的。

    1.1. 通知的生命周期

    Spring的通知可以跨越多個被通知對象共享,或者每個被通知對象有自己的通知。這分別對應(yīng) per-classper-instance 通知。

    Per-class通知使用最為廣泛。它適合于通用的通知,如事務(wù)adisor。它們不依賴被代理 的對象的狀態(tài),也不添加新的狀態(tài)。它們僅僅作用于方法和方法的參數(shù)。

    Per-instance通知適合于導(dǎo)入,來支持混入(mixin)。在這種情況下,通知添加狀態(tài)到 被代理的對象。

    可以在同一個AOP代理中混合使用共享和per-instance通知。

    1.2. Spring中通知類型

    Spring提供幾種現(xiàn)成的通知類型并可擴展提供任意的通知類型。讓我們看看基本概念和標(biāo)準(zhǔn)的通知類型。

    1.2.1. Interception around advice

    Spring中最基本的通知類型是interception around advice .

    Spring使用方法攔截器的around通知是和AOP聯(lián)盟接口兼容的。實現(xiàn)around通知的 類需要實現(xiàn)接口MethodInterceptor

    public interface MethodInterceptor extends Interceptor {

     

        Object invoke(MethodInvocation invocation) throws Throwable;

    }

    invoke()方法的MethodInvocation 參數(shù)暴露將被調(diào)用的方法、目標(biāo)連接點、AOP代理和傳遞給被調(diào)用方法的參數(shù)。 invoke()方法應(yīng)該返回調(diào)用的結(jié)果:連接點的返回值。

    一個簡單的MethodInterceptor實現(xiàn)看起來如下:

    public class DebugInterceptor implements MethodInterceptor {

     

        public Object invoke(MethodInvocation invocation) throws Throwable {

            System.out.println("Before: invocation=[" + invocation + "]");

            Object rval = invocation.proceed();

            System.out.println("Invocation returned");

            return rval;

        }

    }

    注意MethodInvocationproceed()方法的調(diào)用。這個調(diào)用會應(yīng)用到目標(biāo)連接點的攔截器鏈中的每一個攔截器。大部分?jǐn)r截器會調(diào)用這個方法,并返回它的返回值。但是, 一個MethodInterceptor,和任何around通知一樣,可以返回不同的值或者拋出一個異常,而 不調(diào)用proceed方法。但是,沒有好的原因你要這么做。

    MethodInterceptor提供了和其他AOP聯(lián)盟的兼容實現(xiàn)的交互能力。這一節(jié)下面 要討論的其他的通知類型實現(xiàn)了AOP公共的概念,但是以Spring特定的方式。雖然使用特定 通知類型有很多優(yōu)點,但如果你可能需要在其他的AOP框架中使用,請堅持使用MethodInterceptor around通知類型。注意目前切入點不能和其它框架交互操作,并且AOP聯(lián)盟目前也沒有定義切入 點接口。

    1.2.2. Before通知

    Before通知是一種簡單的通知類型。 這個通知不需要一個MethodInvocation對象,因為它只在進入一個方法前被調(diào)用。

    Before通知的主要優(yōu)點是它不需要調(diào)用proceed() 方法, 因此沒有無意中忘掉繼續(xù)執(zhí)行攔截器鏈的可能性。

    MethodBeforeAdvice接口如下所示。 (SpringAPI設(shè)計允許成員變量的before通知,雖然一般的對象都可以應(yīng)用成員變量攔截,但Spring 有可能永遠不會實現(xiàn)它)。

    public interface MethodBeforeAdvice extends BeforeAdvice {

     

        void before(Method m, Object[] args, Object target) throws Throwable;

    }

    注意返回類型是void Before通知可以在連接點執(zhí)行之前 插入自定義的行為,但是不能改變返回值。如果一個before通知拋出一個異常,這將中斷攔截器 鏈的進一步執(zhí)行。這個異常將沿著攔截器鏈后退著向上傳播。如果這個異常是unchecked的,或者 出現(xiàn)在被調(diào)用的方法的簽名中,它將會被直接傳遞給客戶代碼;否則,它將被AOP代理包裝到一個unchecked 的異常里。

    下面是Spring中一個before通知的例子,這個例子計數(shù)所有正常返回的方法:

    public class CountingBeforeAdvice implements MethodBeforeAdvice {

        private int count;

        public void before(Method m, Object[] args, Object target) throws Throwable {

            ++count;

        }

     

        public int getCount() {

            return count;

        }

    }

    Before通知可以被用于任何類型的切入點。

    1.2.3. Throws通知

    如果連接點拋出異常,Throws通知 在連接點返回后被調(diào)用。Spring提供強類型的throws通知。注意這意味著 org.springframework.aop.ThrowsAdvice接口不包含任何方法: 它是一個標(biāo)記接口,標(biāo)識給定的對象實現(xiàn)了一個或多個強類型的throws通知方法。這些方法形式 如下:

    afterThrowing([Method], [args], [target], subclassOfThrowable)

    只有最后一個參數(shù)是必需的。這樣從一個參數(shù)到四個參數(shù),依賴于通知是否對方法和方法 的參數(shù)感興趣。下面是throws通知的例子。

    如果拋出RemoteException異常(包括子類), 這個通知會被調(diào)用

    public class RemoteThrowsAdvice implements ThrowsAdvice {

     

        public void afterThrowing(RemoteException ex) throws Throwable {

            // Do something with remote exception

        }

    }

    如果拋出ServletException異常, 下面的通知會被調(diào)用。和上面的通知不一樣,它聲明了四個參數(shù),所以它可以訪問被調(diào)用的方法,方法的參數(shù)和目標(biāo)對象:

    public static class ServletThrowsAdviceWithArguments implements ThrowsAdvice {

     

        public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {

            // Do something will all arguments

        }

    }

    最后一個例子演示了如何在一個類中使用兩個方法來同時處理 RemoteExceptionServletException 異常。任意個數(shù)的throws方法可以被組合在一個類中。

    public static class CombinedThrowsAdvice implements ThrowsAdvice {

     

        public void afterThrowing(RemoteException ex) throws Throwable {

            // Do something with remote exception

        }

     

        public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {

            // Do something will all arguments

        }

    }

    Throws通知可被用于任何類型的切入點。

    1.2.4. After Returning通知

    Spring中的after returning通知必須實現(xiàn) org.springframework.aop.AfterReturningAdvice 接口,如下所示:

    public interface AfterReturningAdvice extends Advice {

     

        void afterReturning(Object returnValue, Method m, Object[] args, Object target)

                throws Throwable;

    }

    After returning通知可以訪問返回值(不能改變)、被調(diào)用的方法、方法的參數(shù)和目標(biāo)對象。

    下面的after returning通知統(tǒng)計所有成功的沒有拋出異常的方法調(diào)用:

    public class CountingAfterReturningAdvice implements AfterReturningAdvice {

        private int count;

     

        public void afterReturning(Object returnValue, Method m, Object[] args, Object target) throws Throwable {

            ++count;

        }

     

        public int getCount() {

            return count;

        }

    }

    這方法不改變執(zhí)行路徑。如果它拋出一個異常,這個異常而不是返回值將被沿著攔截器鏈向上拋出。

    After returning通知可被用于任何類型的切入點。

    1.2.5. Introduction通知

    Springintroduction通知看作一種特殊類型的攔截通知。

    Introduction需要實現(xiàn)IntroductionAdvisor, IntroductionInterceptor接口:

    public interface IntroductionInterceptor extends MethodInterceptor {

     

        boolean implementsInterface(Class intf);

    }

    繼承自AOP聯(lián)盟MethodInterceptor接口的 invoke()方法必須實現(xiàn)導(dǎo)入:也就是說,如果被調(diào)用的方法是在 導(dǎo)入的接口中,導(dǎo)入攔截器負(fù)責(zé)處理這個方法調(diào)用,它不能調(diào)用proceed() 方法。

    Introduction通知不能被用于任何切入點,因為它只能作用于類層次上,而不是方法。你可以只用InterceptionIntroductionAdvisor來實現(xiàn)導(dǎo)入通知,它有下面的方法:

    public interface InterceptionIntroductionAdvisor extends InterceptionAdvisor {

     

        ClassFilter getClassFilter();

     

        IntroductionInterceptor getIntroductionInterceptor();

     

        Class[] getInterfaces();

    }

    這里沒有MethodMatcher,因此也沒有和導(dǎo)入通知關(guān)聯(lián)的 切入點。只有類過濾是合乎邏輯的。

    getInterfaces()方法返回advisor導(dǎo)入的接口。

    讓我們看看一個來自Spring測試套件中的簡單例子。我們假設(shè)想要導(dǎo)入下面的接口到一個 或者多個對象中:

    public interface Lockable {

        void lock();

        void unlock();

        boolean locked();

    }

    這個例子演示了一個mixin。我們想要能夠 將被通知對象類型轉(zhuǎn)換為Lockable,不管它們的類型,并且調(diào)用lockunlock方法。如果我們調(diào)用 lock()方法,我們希望所有setter方法拋出LockedException異常。這樣我們能添加一個方面使的對象不可變,而它們不需要知道這一點:這是一個很好的AOP例 子。

    首先,我們需要一個做大量轉(zhuǎn)化的IntroductionInterceptor。 在這里,我們繼承 org.springframework.aop.support.DelegatingIntroductionInterceptor 實用類。我們可以直接實現(xiàn)IntroductionInterceptor接口,但是大多數(shù)情況下 DelegatingIntroductionInterceptor是最合適的。

    DelegatingIntroductionInterceptor的設(shè)計是將導(dǎo)入 委托到真正實現(xiàn)導(dǎo)入接口的接口,隱藏完成這些工作的攔截器。委托可以使用構(gòu)造方法參數(shù) 設(shè)置到任何對象中;默認(rèn)的委托就是自己(當(dāng)無參數(shù)的構(gòu)造方法被使用時)。這樣在下面的例子里,委托是DelegatingIntroductionInterceptor的子類 LockMixin。給定一個委托(默認(rèn)是自身)的 DelegatingIntroductionInterceptor實例尋找被這個委托(而不 是IntroductionInterceptor)實現(xiàn)的所有接口,并支持它們中任何一個導(dǎo)入。子類如 LockMixin也可能調(diào)用suppressInterflace(Class intf) 方法隱藏不應(yīng)暴露的接口。然而,不管IntroductionInterceptor 準(zhǔn)備支持多少接口,IntroductionAdvisor將控制哪個接口將被實際 暴露。一個導(dǎo)入的接口將隱藏目標(biāo)的同一個接口的所有實現(xiàn)。

    這樣,LockMixin繼承DelegatingIntroductionInterceptor 并自己實現(xiàn)Lockable。父類自動選擇支持導(dǎo)入的Lockable,所以我們不需要指定它。用這種方法我們可以導(dǎo)入任意數(shù)量的接口。

    注意locked實例變量的使用。這有效地添加額外的狀態(tài)到目標(biāo) 對象。

    public class LockMixin extends DelegatingIntroductionInterceptor

        implements Lockable {

     

        private boolean locked;

     

        public void lock() {

            this.locked = true;

        }

     

        public void unlock() {

            this.locked = false;

        }

     

        public boolean locked() {

            return this.locked;

        }

     

        public Object invoke(MethodInvocation invocation) throws Throwable {

            if (locked() && invocation.getMethod().getName().indexOf("set") == 0)

                throw new LockedException();

            return super.invoke(invocation);

        }

     

    }

    通常不要需要改寫invoke()方法:實現(xiàn) DelegatingIntroductionInterceptor就足夠了,如果是導(dǎo)入的方法, DelegatingIntroductionInterceptor實現(xiàn)會調(diào)用委托方法, 否則繼續(xù)沿著連接點處理。在現(xiàn)在的情況下,我們需要添加一個檢查:在上鎖狀態(tài)下不能調(diào)用setter方法。

    所需的導(dǎo)入advisor是很簡單的。只有保存一個獨立的 LockMixin實例,并指定導(dǎo)入的接口,在這里就是 Lockable。一個稍微復(fù)雜一點例子可能需要一個導(dǎo)入攔截器(可以 定義成prototype)的引用:在這種情況下,LockMixin沒有相關(guān)配置,所以我們簡單地 使用new來創(chuàng)建它。

    public class LockMixinAdvisor extends DefaultIntroductionAdvisor {

     

        public LockMixinAdvisor() {

            super(new LockMixin(), Lockable.class);

        }

    }

    我們可以非常簡單地使用這個advisor:它不需要任何配置。(但是,有一點 必要的:就是不可能在沒有IntroductionAdvisor 的情況下使用IntroductionInterceptor。) 和導(dǎo)入一樣,通常 advisor必須是針對每個實例的,并且是有狀態(tài)的。我們會有不同的的LockMixinAdvisor 每個被通知對象,會有不同的LockMixin advisor組成了被通知對象的狀態(tài)的一部分。

    和其他advisor一樣,我們可以使用 Advised.addAdvisor() 方法以編程地方式使用這種advisor,或者在XML中配置(推薦這種方式)。 下面將討論所有代理創(chuàng)建,包括自動代理創(chuàng)建者,選擇代理創(chuàng)建以正確地處理導(dǎo)入和有狀態(tài)的混入。

     

     

    參考資料:

    1. http://www.javaresearch.org/article/showarticle.jsp?column=23&thread=41315

    2. http://tech.ccidnet.com/art/1112/20051114/371959_5.html

    3. http://www.7dspace.com/doc/21/0603/20063305365394884.htm

    4. http://barton131420.cnblogs.com/articles/280664.html

    5. http://www.opentown.info/bbs/viewtopic.php?t=7

     

    posted on 2007-06-28 09:36 junky 閱讀(712) 評論(0)  編輯  收藏 所屬分類: spring

    主站蜘蛛池模板: 亚洲国模精品一区| 日本亚洲中午字幕乱码| 亚洲综合色区在线观看| 99久久免费国产精品特黄| 青青操在线免费观看| 精品韩国亚洲av无码不卡区| 亚洲人成日本在线观看| 久久久久亚洲精品成人网小说| 国产一区二区三区在线免费观看| 久热中文字幕在线精品免费| 暖暖免费在线中文日本| eeuss免费天堂影院| 精品久久久久亚洲| 亚洲色大成网站www尤物| 亚洲国产成人精品电影| 久久久无码精品亚洲日韩蜜臀浪潮| 久久久久亚洲精品无码网址 | 免费在线观看的网站| 污污网站18禁在线永久免费观看| 亚洲精品视频免费观看| 黄色一级免费网站| 看Aⅴ免费毛片手机播放| 亚洲高清毛片一区二区| 亚洲中文字幕无码一去台湾| 亚洲天堂一区二区三区| 亚洲国产品综合人成综合网站| 亚洲精品视频在线播放| 亚洲黄色免费观看| 亚洲理论片在线观看| 亚洲国产高清美女在线观看| 久久亚洲精品无码aⅴ大香| 亚洲精品免费在线| 亚洲无圣光一区二区| 亚洲二区在线视频| 学生妹亚洲一区二区| 亚洲综合精品成人| 性色av极品无码专区亚洲| 国产亚洲综合一区二区三区| 香蕉视频免费在线播放| 国产精品hd免费观看| 免费91麻豆精品国产自产在线观看 |