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

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

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

    The important thing in life is to have a great aim , and the determination

    常用鏈接

    統(tǒng)計

    IT技術(shù)鏈接

    保險相關(guān)

    友情鏈接

    基金知識

    生活相關(guān)

    最新評論

    Spring源代碼解析(四):Spring AOP獲取Proxy

    下面我們來看看Spring的AOP的一些相關(guān)代碼是怎么得到Proxy的,讓我們我們先看看AOP和Spring AOP的一些基本概念:
    Advice:
        通知,制定在連接點做什么,在Sping中,他主要描述Spring圍繞方法調(diào)用注入的額外的行為,Spring提供的通知類型有:
        before advice,AfterReturningAdvice,ThrowAdvice,MethodBeforeAdvice,這些都是Spring AOP定義的接口類,具體的動作實現(xiàn)需要用戶程序來完成。
    Pointcut:
        切點,其決定一個advice應(yīng)該應(yīng)用于哪個連接點,也就是需要插入額外處理的地方的集合,例如,被某個advice作為目標(biāo)的一組方法。Spring pointcut通常意味著標(biāo)示方法,可以選擇一組方法調(diào)用作為pointcut,Spring提供了具體的切點來給用戶使用,比如正則表達式切點 JdkRegexpMethodPointcut通過正則表達式對方法名進行匹配,其通過使用 AbstractJdkRegexpMethodPointcut中的對MethodMatcher接口的實現(xiàn)來完成pointcut功能:
    Java代碼 復(fù)制代碼 收藏代碼
    1. public final boolean matches(Method method, Class targetClass) {   
    2.     //這里通過放射得到方法的全名   
    3.     String patt = method.getDeclaringClass().getName() + "." + method.getName();   
    4.     for (int i = 0; i < this.patterns.length; i++) {   
    5.         // 這里是判斷是否和方法名是否匹配的代碼   
    6.         boolean matched = matches(patt, i);   
    7.         if (matched) {   
    8.             for (int j = 0; j < this.excludedPatterns.length; j++) {   
    9.                 boolean excluded = matchesExclusion(patt, j);   
    10.                 if(excluded) {   
    11.                     return false;   
    12.                 }   
    13.             }   
    14.             return true;   
    15.         }   
    16.     }   
    17.     return false;   
    18. }  

    在JDKRegexpMethodPointcut中通過JDK中的正則表達式匹配來完成pointcut的最終確定:
    Java代碼 復(fù)制代碼 收藏代碼
    1. protected boolean matches(String pattern, int patternIndex) {   
    2.     Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);   
    3.     return matcher.matches();   
    4. }  

    Advisor:
    當(dāng)我們完成額外的動作設(shè)計(advice)和額外動作插入點的設(shè)計(pointcut)以后,我們需要一個對象把他們結(jié)合起來,這就是通知器 - advisor,定義應(yīng)該在哪里應(yīng)用哪個通知。Advisor的實現(xiàn)有:DefaultPointcutAdvisor他有兩個屬性advice和 pointcut來讓我們配置advice和pointcut。
    接著我們就可以通過ProxyFactoryBean來配置我們的代理對象和方面行為,在ProxyFactoryBean中有interceptorNames來配置已經(jīng)定義好的通知器-advisor,雖然這里的名字叫做interceptNames,但實際上是供我們配置advisor的地方,具體的代理實現(xiàn)通過JDK 的Proxy或者CGLIB來完成。因為ProxyFactoryBean是一個FactoryBean,在ProxyFactoryBean中我們通過getObject()可以直接得到代理對象:
    Java代碼 復(fù)制代碼 收藏代碼
    1. public Object getObject() throws BeansException {   
    2.     //這里初始化通知器鏈   
    3.     initializeAdvisorChain();   
    4.     if (isSingleton()) {   
    5.     //根據(jù)定義需要生成單件的Proxy   
    6.         return getSingletonInstance();   
    7.     }   
    8.     else {   
    9.     .......   
    10.         //這里根據(jù)定義需要生成Prototype類型的Proxy   
    11.         return newPrototypeInstance();   
    12.     }   
    13. }  

    我們看看怎樣生成單件的代理對象:
    Java代碼 復(fù)制代碼 收藏代碼
    1. private synchronized Object getSingletonInstance() {   
    2.     if (this.singletonInstance == null) {   
    3.         this.targetSource = freshTargetSource();   
    4.         if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {   
    5.             // 這里設(shè)置代理對象的接口   
    6.             setInterfaces(ClassUtils.getAllInterfacesForClass(this.targetSource.getTargetClass()));   
    7.         }   
    8.         // Eagerly initialize the shared singleton instance.   
    9.         super.setFrozen(this.freezeProxy);   
    10.         // 注意這里的方法會使用ProxyFactory來生成我們需要的Proxy   
    11.         this.singletonInstance = getProxy(createAopProxy());   
    12.         // We must listen to superclass advice change events to recache the singleton   
    13.         // instance if necessary.   
    14.         addListener(this);   
    15.     }   
    16.     return this.singletonInstance;   
    17. }   
    18.   
    19. //使用createAopProxy放回的AopProxy來得到代理對象。   
    20. protected Object getProxy(AopProxy aopProxy) {   
    21.     return aopProxy.getProxy(this.beanClassLoader);   
    22. }  

    ProxyFactoryBean的父類是AdvisedSupport,Spring使用AopProxy接口把AOP代理的實現(xiàn)與框架的其他部分分離開來;在AdvisedSupport中通過這樣的方式來得到AopProxy,當(dāng)然這里需要得到AopProxyFactory的幫助 - 下面我們看到Spring為我們提供的實現(xiàn),來幫助我們方便的從JDK或者cglib中得到我們想要的代理對象:
    Java代碼 復(fù)制代碼 收藏代碼
    1. protected synchronized AopProxy createAopProxy() {   
    2.     if (!this.isActive) {   
    3.         activate();   
    4.     }   
    5.     return getAopProxyFactory().createAopProxy(this);   
    6. }  

    而在ProxyConfig中對使用的AopProxyFactory做了定義:
    Java代碼 復(fù)制代碼 收藏代碼
    1. //這個DefaultAopProxyFactory是Spring用來生成AopProxy的地方,   
    2. //當(dāng)然了它包含JDK和Cglib兩種實現(xiàn)方式。   
    3. private transient AopProxyFactory aopProxyFactory = new DefaultAopProxyFactory();  

    其中在DefaultAopProxyFactory中是這樣生成AopProxy的:
    Java代碼 復(fù)制代碼 收藏代碼
    1. public AopProxy createAopProxy(AdvisedSupport advisedSupport) throws AopConfigException {   
    2.     //首先考慮使用cglib來實現(xiàn)代理對象,當(dāng)然如果同時目標(biāo)對象不是接口的實現(xiàn)類的話   
    3.     if (advisedSupport.isOptimize() || advisedSupport.isProxyTargetClass() ||   
    4.         advisedSupport.getProxiedInterfaces().length == 0) {   
    5.         //這里判斷如果不存在cglib庫,直接拋出異常。   
    6.         if (!cglibAvailable) {   
    7.             throw new AopConfigException(   
    8.                     "Cannot proxy target class because CGLIB2 is not available. " +   
    9.                     "Add CGLIB to the class path or specify proxy interfaces.");   
    10.         }   
    11.         // 這里使用Cglib來生成Proxy,如果target不是接口的實現(xiàn)的話,返回cglib類型的AopProxy   
    12.         return CglibProxyFactory.createCglibProxy(advisedSupport);   
    13.     }   
    14.     else {   
    15.         // 這里使用JDK來生成Proxy,返回JDK類型的AopProxy   
    16.         return new JdkDynamicAopProxy(advisedSupport);   
    17.     }   
    18. }  

    于是我們就可以看到其中的代理對象可以由JDK或者Cglib來生成,我們看到JdkDynamicAopProxy類和Cglib2AopProxy都實現(xiàn)的是AopProxy的接口,在JdkDynamicAopProxy實現(xiàn)中我們可以看到Proxy是怎樣生成的:
    Java代碼 復(fù)制代碼 收藏代碼
    1. public Object getProxy(ClassLoader classLoader) {   
    2.     if (logger.isDebugEnabled()) {   
    3.         Class targetClass = this.advised.getTargetSource().getTargetClass();   
    4.         logger.debug("Creating JDK dynamic proxy" +   
    5.                 (targetClass != null ? " for [" + targetClass.getName() + "]" : ""));   
    6.     }   
    7.     Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);   
    8.     findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);   
    9.     //這里我們調(diào)用JDK Proxy來生成需要的Proxy實例   
    10.     return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);   
    11. }  

    這樣用Proxy包裝target之后,通過ProxyFactoryBean得到對其方法的調(diào)用就被Proxy攔截了, ProxyFactoryBean的getObject()方法得到的實際上是一個Proxy了,我們的target對象已經(jīng)被封裝了。對 ProxyFactoryBean這個工廠bean而言,其生產(chǎn)出來的對象是封裝了目標(biāo)對象的代理對象。

    posted on 2011-10-26 23:39 鴻雁 閱讀(243) 評論(0)  編輯  收藏


    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 亚洲精品一二三区| 三根一起会坏掉的好痛免费三级全黄的视频在线观看 | 亚洲av永久无码精品天堂久久| 久久久久亚洲AV无码永不| 亚洲一区二区三区不卡在线播放 | 亚洲综合无码精品一区二区三区| 亚洲性日韩精品一区二区三区| 久久影视国产亚洲| 亚洲成人免费网址| 精品在线观看免费| 6080午夜一级毛片免费看6080夜福利 | 四虎影院永久免费观看| a级特黄毛片免费观看| 日韩免费在线视频| 在线播放高清国语自产拍免费| 免费国产不卡午夜福在线| 亚洲国产国产综合一区首页| 色老板亚洲视频免在线观| 两个人看的www免费视频| 青草草在线视频永久免费| 亚洲国产精品成人精品无码区 | 添bbb免费观看高清视频| 久久国产精品2020免费m3u8 | 亚洲一区二区三区自拍公司| 亚洲狠狠成人综合网| 99在线观看免费视频| 久久久久亚洲?V成人无码| 国产午夜亚洲精品国产| 中文字幕免费在线看线人| 国产亚洲AV夜间福利香蕉149| 美女被暴羞羞免费视频| 日本成人免费在线| 亚洲日本在线电影| 成人免费淫片在线费观看 | 99热在线日韩精品免费| 亚洲免费日韩无码系列| 免费无码AV一区二区| 亚洲AV无码一区二区三区在线观看| 亚洲精品欧美综合四区| 韩国欧洲一级毛片免费| 国产亚洲漂亮白嫩美女在线|