<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的通知可以跨越多個被通知對象共享,或者每個被通知對象有自己的通知。這分別對應 per-classper-instance 通知。

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

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

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

    1.2. Spring中通知類型

    Spring提供幾種現(xià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ù)暴露將被調用的方法、目標連接點、AOP代理和傳遞給被調用方法的參數(shù)。 invoke()方法應該返回調用的結果:連接點的返回值。

    一個簡單的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()方法的調用。這個調用會應用到目標連接點的攔截器鏈中的每一個攔截器。大部分攔截器會調用這個方法,并返回它的返回值。但是, 一個MethodInterceptor,和任何around通知一樣,可以返回不同的值或者拋出一個異常,而 不調用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對象,因為它只在進入一個方法前被調用。

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

    MethodBeforeAdvice接口如下所示。 (SpringAPI設計允許成員變量的before通知,雖然一般的對象都可以應用成員變量攔截,但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)在被調用的方法的簽名中,它將會被直接傳遞給客戶代碼;否則,它將被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通知 在連接點返回后被調用。Spring提供強類型的throws通知。注意這意味著 org.springframework.aop.ThrowsAdvice接口不包含任何方法: 它是一個標記接口,標識給定的對象實現(xiàn)了一個或多個強類型的throws通知方法。這些方法形式 如下:

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

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

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

    public class RemoteThrowsAdvice implements ThrowsAdvice {

     

        public void afterThrowing(RemoteException ex) throws Throwable {

            // Do something with remote exception

        }

    }

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

    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通知可以訪問返回值(不能改變)、被調用的方法、方法的參數(shù)和目標對象。

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

    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)導入:也就是說,如果被調用的方法是在 導入的接口中,導入攔截器負責處理這個方法調用,它不能調用proceed() 方法。

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

    public interface InterceptionIntroductionAdvisor extends InterceptionAdvisor {

     

        ClassFilter getClassFilter();

     

        IntroductionInterceptor getIntroductionInterceptor();

     

        Class[] getInterfaces();

    }

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

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

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

    public interface Lockable {

        void lock();

        void unlock();

        boolean locked();

    }

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

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

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

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

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

    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就足夠了,如果是導入的方法, DelegatingIntroductionInterceptor實現(xiàn)會調用委托方法, 否則繼續(xù)沿著連接點處理。在現(xiàn)在的情況下,我們需要添加一個檢查:在上鎖狀態(tài)下不能調用setter方法。

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

    public class LockMixinAdvisor extends DefaultIntroductionAdvisor {

     

        public LockMixinAdvisor() {

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

        }

    }

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

    和其他advisor一樣,我們可以使用 Advised.addAdvisor() 方法以編程地方式使用這種advisor,或者在XML中配置(推薦這種方式)。 下面將討論所有代理創(chuàng)建,包括自動代理創(chuàng)建者,選擇代理創(chuàng)建以正確地處理導入和有狀態(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 閱讀(713) 評論(0)  編輯  收藏 所屬分類: spring

    主站蜘蛛池模板: 亚洲色成人网站WWW永久四虎 | 亚洲精品视频在线观看你懂的| 成人嫩草影院免费观看| 国产AV无码专区亚洲AV毛网站| 久久久久久精品免费看SSS| 亚洲av无一区二区三区| 国产亚洲精品精品国产亚洲综合 | 免费午夜爽爽爽WWW视频十八禁| 三年片免费高清版| 亚洲人成网站色在线观看| 亚洲人成影院在线无码观看| 亚洲精品视频免费看| 色欲aⅴ亚洲情无码AV| 久久亚洲国产成人精品性色| 国产高清在线精品免费软件| 久久99精品免费视频| 羞羞漫画小舞被黄漫免费| 在线观看亚洲人成网站| 亚洲精品在线视频| 最近免费中文字幕4| 久久精品国产免费一区| 在线观看亚洲电影| 亚洲精品456人成在线| 亚洲av无码专区国产乱码在线观看 | 一级视频免费观看| 亚洲av无码片在线观看| 亚洲AV无码欧洲AV无码网站| 免费人成年激情视频在线观看| 免费观看激色视频网站(性色)| 97在线免费视频| 污污视频网站免费观看| 久久亚洲国产最新网站| 亚洲激情在线观看| 国产亚洲精品资源在线26u| 免费亚洲视频在线观看| 成人免费毛片内射美女APP| 久久久久久国产精品免费免费男同| 高清免费久久午夜精品| 亚洲成AV人影片在线观看| 亚洲图片激情小说| 亚洲人成网址在线观看|