<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ù)鏈接

    保險相關

    友情鏈接

    基金知識

    生活相關

    最新評論

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

    下面我們來看看Spring的AOP的一些相關代碼是怎么得到Proxy的,讓我們我們先看看AOP和Spring AOP的一些基本概念:
    Advice:
        通知,制定在連接點做什么,在Sping中,他主要描述Spring圍繞方法調(diào)用注入的額外的行為,Spring提供的通知類型有:
        before advice,AfterReturningAdvice,ThrowAdvice,MethodBeforeAdvice,這些都是Spring AOP定義的接口類,具體的動作實現(xiàn)需要用戶程序來完成。
    Pointcut:
        切點,其決定一個advice應該應用于哪個連接點,也就是需要插入額外處理的地方的集合,例如,被某個advice作為目標的一組方法。Spring pointcut通常意味著標示方法,可以選擇一組方法調(diào)用作為pointcut,Spring提供了具體的切點來給用戶使用,比如正則表達式切點 JdkRegexpMethodPointcut通過正則表達式對方法名進行匹配,其通過使用 AbstractJdkRegexpMethodPointcut中的對MethodMatcher接口的實現(xiàn)來完成pointcut功能:
    Java代碼 復制代碼 收藏代碼
    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代碼 復制代碼 收藏代碼
    1. protected boolean matches(String pattern, int patternIndex) {   
    2.     Matcher matcher = this.compiledPatterns[patternIndex].matcher(pattern);   
    3.     return matcher.matches();   
    4. }  

    Advisor:
    當我們完成額外的動作設計(advice)和額外動作插入點的設計(pointcut)以后,我們需要一個對象把他們結(jié)合起來,這就是通知器 - advisor,定義應該在哪里應用哪個通知。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代碼 復制代碼 收藏代碼
    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代碼 復制代碼 收藏代碼
    1. private synchronized Object getSingletonInstance() {   
    2.     if (this.singletonInstance == null) {   
    3.         this.targetSource = freshTargetSource();   
    4.         if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {   
    5.             // 這里設置代理對象的接口   
    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,當然這里需要得到AopProxyFactory的幫助 - 下面我們看到Spring為我們提供的實現(xiàn),來幫助我們方便的從JDK或者cglib中得到我們想要的代理對象:
    Java代碼 復制代碼 收藏代碼
    1. protected synchronized AopProxy createAopProxy() {   
    2.     if (!this.isActive) {   
    3.         activate();   
    4.     }   
    5.     return getAopProxyFactory().createAopProxy(this);   
    6. }  

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

    其中在DefaultAopProxyFactory中是這樣生成AopProxy的:
    Java代碼 復制代碼 收藏代碼
    1. public AopProxy createAopProxy(AdvisedSupport advisedSupport) throws AopConfigException {   
    2.     //首先考慮使用cglib來實現(xiàn)代理對象,當然如果同時目標對象不是接口的實現(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代碼 復制代碼 收藏代碼
    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)出來的對象是封裝了目標對象的代理對象。

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


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


    網(wǎng)站導航:
     
    主站蜘蛛池模板: 久久亚洲国产精品123区| 亚洲精品成人无限看| 视频一区二区三区免费观看| 亚洲人成电影网站国产精品| 99精品视频在线视频免费观看| 亚洲天堂一区二区三区四区| 国产免费观看a大片的网站| 国产精品九九久久免费视频| 亚洲黄色三级网站| 免费a在线观看播放| 免费A级毛片无码专区| 婷婷亚洲综合五月天小说在线| 亚洲国产成人精品无码区在线观看 | 亚洲综合激情九月婷婷| 国产午夜无码视频免费网站| 久爱免费观看在线网站| 国产亚洲精品美女| 亚洲午夜精品久久久久久人妖| 四虎影视在线永久免费观看| 在线免费观看亚洲| 一级成人生活片免费看| 亚洲午夜在线播放| 人人狠狠综合久久亚洲88| 日本特黄a级高清免费大片| 最近中文字幕大全中文字幕免费| eeuss在线兵区免费观看| 精品久久久久久亚洲精品| 久久久青草青青亚洲国产免观| 成人免费视频国产| 在线观看免费av网站| 久久久WWW免费人成精品| 亚洲av无码无线在线观看| 亚洲黄色免费网址| 亚洲桃色AV无码| 无码不卡亚洲成?人片| 国内自产少妇自拍区免费| **真实毛片免费观看 | 操美女视频免费网站| 午夜不卡久久精品无码免费| 精品多毛少妇人妻AV免费久久| 亚洲AV日韩综合一区|