<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

    常用鏈接

    統計

    IT技術鏈接

    保險相關

    友情鏈接

    基金知識

    生活相關

    最新評論

    Spring源代碼解析(六):Spring AOP中對攔截器調用的實現

    前面我們分析了Spring AOP實現中得到Proxy對象的過程,下面我們看看在Spring AOP中攔截器鏈是怎樣被調用的,也就是Proxy模式是怎樣起作用的,或者說Spring是怎樣為我們提供AOP功能的;
    在JdkDynamicAopProxy中生成Proxy對象的時候:
    Java代碼 復制代碼 收藏代碼
    1. return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);  

    這里的this參數對應的是InvocationHandler對象,這里我們的JdkDynamicAopProxy實現了這個接口,也就是說當Proxy對象的函數被調用的時候,這個InvocationHandler的invoke方法會被作為回調函數調用,下面我們看看這個方法的實現:
    Java代碼 復制代碼 收藏代碼
    1. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {   
    2.     MethodInvocation invocation = null;   
    3.     Object oldProxy = null;   
    4.     boolean setProxyContext = false;   
    5.   
    6.     TargetSource targetSource = this.advised.targetSource;   
    7.     Class targetClass = null;   
    8.     Object target = null;   
    9.   
    10.     try {   
    11.         // Try special rules for equals() method and implementation of the   
    12.         // Advised AOP configuration interface.   
    13.   
    14.         if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {   
    15.             // What if equals throws exception!?   
    16.             // This class implements the equals(Object) method itself.   
    17.             return equals(args[0]) ? Boolean.TRUE : Boolean.FALSE;   
    18.         }   
    19.         if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {   
    20.             // This class implements the hashCode() method itself.   
    21.             return new Integer(hashCode());   
    22.         }   
    23.         if (Advised.class == method.getDeclaringClass()) {   
    24.             // service invocations on ProxyConfig with the proxy config   
    25.             return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);   
    26.         }   
    27.   
    28.         Object retVal = null;   
    29.   
    30.         if (this.advised.exposeProxy) {   
    31.             // make invocation available if necessary   
    32.             oldProxy = AopContext.setCurrentProxy(proxy);   
    33.             setProxyContext = true;   
    34.         }   
    35.   
    36.         // May be <code>null</code>. Get as late as possible to minimize the time we "own" the target,   
    37.         // in case it comes from a pool.   
    38.         // 這里是得到目標對象的地方,當然這個目標對象可能來自于一個實例池或者是一個簡單的JAVA對象   
    39.         target = targetSource.getTarget();   
    40.         if (target != null) {   
    41.             targetClass = target.getClass();   
    42.         }   
    43.   
    44.         // get the interception chain for this method   
    45.         // 這里獲得定義好的攔截器鏈   
    46.         List chain = this.advised.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(   
    47.                 this.advised, proxy, method, targetClass);   
    48.   
    49.         // Check whether we have any advice. If we don't, we can fallback on direct   
    50.         // reflective invocation of the target, and avoid creating a MethodInvocation.   
    51.         // 如果沒有設定攔截器,那么我們就直接調用目標的對應方法   
    52.         if (chain.isEmpty()) {   
    53.             // We can skip creating a MethodInvocation: just invoke the target directly   
    54.             // Note that the final invoker must be an InvokerInterceptor so we know it does   
    55.             // nothing but a reflective operation on the target, and no hot swapping or fancy proxying   
    56.             retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);   
    57.         }   
    58.         else {   
    59.             // We need to create a method invocation...   
    60.             // invocation = advised.getMethodInvocationFactory().getMethodInvocation(   
    61.             //         proxy, method, targetClass, target, args, chain, advised);   
    62.             // 如果有攔截器的設定,那么需要調用攔截器之后才調用目標對象的相應方法   
    63.             // 這里通過構造一個ReflectiveMethodInvocation來實現,下面我們會看這個ReflectiveMethodInvocation類   
    64.             invocation = new ReflectiveMethodInvocation(   
    65.                     proxy, target, method, args, targetClass, chain);   
    66.   
    67.             // proceed to the joinpoint through the interceptor chain   
    68.             // 這里通過ReflectiveMethodInvocation來調用攔截器鏈和相應的目標方法   
    69.             retVal = invocation.proceed();   
    70.         }   
    71.   
    72.         // massage return value if necessary   
    73.         if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy)) {   
    74.             // Special case: it returned "this" and the return type of the method is type-compatible   
    75.             // Note that we can't help if the target sets   
    76.             // a reference to itself in another returned object.   
    77.             retVal = proxy;   
    78.         }   
    79.         return retVal;   
    80.     }   
    81.     finally {   
    82.         if (target != null && !targetSource.isStatic()) {   
    83.             // must have come from TargetSource   
    84.             targetSource.releaseTarget(target);   
    85.         }   
    86.   
    87.         if (setProxyContext) {   
    88.             // restore old proxy   
    89.             AopContext.setCurrentProxy(oldProxy);   
    90.         }   
    91.     }   
    92. }  

    我們先看看目標對象方法的調用,這里是通過AopUtils的方法調用 - 使用反射機制來對目標對象的方法進行調用:
    Java代碼 復制代碼 收藏代碼
    1. public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)   
    2.     throws Throwable {   
    3.   
    4.     // Use reflection to invoke the method.   
    5.     // 利用放射機制得到相應的方法,并且調用invoke   
    6.     try {   
    7.         if (!Modifier.isPublic(method.getModifiers()) ||   
    8.                 !Modifier.isPublic(method.getDeclaringClass().getModifiers())) {   
    9.             method.setAccessible(true);   
    10.         }   
    11.         return method.invoke(target, args);   
    12.     }   
    13.     catch (InvocationTargetException ex) {   
    14.         // Invoked method threw a checked exception.   
    15.         // We must rethrow it. The client won't see the interceptor.   
    16.         throw ex.getTargetException();   
    17.     }   
    18.     catch (IllegalArgumentException ex) {   
    19.         throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +   
    20.                 method + "] on target [" + target + "]", ex);   
    21.     }   
    22.     catch (IllegalAccessException ex) {   
    23.         throw new AopInvocationException("Couldn't access method: " + method, ex);   
    24.     }   
    25. }  

    對攔截器鏈的調用處理是在ReflectiveMethodInvocation里實現的:
    Java代碼 復制代碼 收藏代碼
    1. public Object proceed() throws Throwable {   
    2.     //    We start with an index of -1 and increment early.   
    3.     // 這里直接調用目標對象的方法,沒有攔截器的調用或者攔截器已經調用完了,這個currentInterceptorIndex的初始值是0   
    4.     if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size()) {   
    5.         return invokeJoinpoint();   
    6.     }   
    7.   
    8.     Object interceptorOrInterceptionAdvice =   
    9.         this.interceptorsAndDynamicMethodMatchers.get(this.currentInterceptorIndex);   
    10.     if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {   
    11.         // Evaluate dynamic method matcher here: static part will already have   
    12.         // been evaluated and found to match.   
    13.         // 這里獲得相應的攔截器,如果攔截器可以匹配的上的話,那就調用攔截器的invoke方法   
    14.         InterceptorAndDynamicMethodMatcher dm =   
    15.             (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;   
    16.         if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {   
    17.             return dm.interceptor.invoke(nextInvocation());   
    18.         }   
    19.         else {   
    20.             // Dynamic matching failed.   
    21.             // Skip this interceptor and invoke the next in the chain.   
    22.             // 如果攔截器匹配不上,那就調用下一個攔截器,這個時候攔截器鏈的位置指示后移并迭代調用當前的proceed方法   
    23.             this.currentInterceptorIndex++;   
    24.             return proceed();   
    25.         }   
    26.     }   
    27.     else {   
    28.         // It's an interceptor, so we just invoke it: The pointcut will have   
    29.         // been evaluated statically before this object was constructed.   
    30.         return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(nextInvocation());   
    31.     }   
    32. }  

    這里把當前的攔截器鏈以及在攔截器鏈的位置標志都clone到一個MethodInvocation對象了,作用是當前的攔截器執行完之后,會繼續沿著得到這個攔截器鏈執行下面的攔截行為,也就是會迭代的調用上面這個proceed:
    Java代碼 復制代碼 收藏代碼
    1. private ReflectiveMethodInvocation nextInvocation() throws CloneNotSupportedException {   
    2.     ReflectiveMethodInvocation invocation = (ReflectiveMethodInvocation) clone();   
    3.     invocation.currentInterceptorIndex = this.currentInterceptorIndex + 1;   
    4.     invocation.parent = this;   
    5.     return invocation;   
    6. }  

    這里的nextInvocation就已經包含了當前的攔截鏈的基本信息,我們看到在Interceptor中的實現比如TransactionInterceptor的實現中:
    Java代碼 復制代碼 收藏代碼
    1. public Object invoke(final MethodInvocation invocation) throws Throwable {   
    2.    ......//這里是TransactionInterceptor插入的事務處理代碼,我們會在后面分析事務處理實現的時候進行分析   
    3.         try {   
    4.             //這里是對配置的攔截器鏈進行迭代處理的調用   
    5.             retVal = invocation.proceed();   
    6.         }   
    7.    ......//省略了和事務處理的異常處理代碼 ,也是TransactionInterceptor插入的處理   
    8.       else {   
    9.         try {   
    10.             Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr,   
    11.                     new TransactionCallback() {   
    12.                         public Object doInTransaction(TransactionStatus status) {   
    13.                              //這里是TransactionInterceptor插入對事務處理的代碼   
    14.                             TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);   
    15.                             //這里是對配置的攔截器鏈進行迭代處理的調用,接著順著攔截器進行處理   
    16.                             try {                           
    17.                                 return invocation.proceed();   
    18.                             }   
    19.    ......//省略了和事務處理的異常處理代碼 ,也是TransactionInterceptor插入的處理   
    20.    }  

    從上面的分析我們看到了Spring AOP的基本實現,比如Spring怎樣得到Proxy,怎樣利用JAVA Proxy以及反射機制對用戶定義的攔截器鏈進行處理。

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


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


    網站導航:
     
    主站蜘蛛池模板: 亚洲最大无码中文字幕| 亚洲精品在线网站| 国产亚洲Av综合人人澡精品| 在线观看日本免费a∨视频| 亚洲视频免费一区| 1000部夫妻午夜免费| 亚洲午夜精品一区二区公牛电影院| 1000部免费啪啪十八未年禁止观看| 亚洲天堂中文字幕| 一二三四免费观看在线视频中文版| 亚洲妓女综合网99| 好吊妞在线成人免费| 国产成人精品亚洲| 亚洲色成人中文字幕网站| 久久青草国产免费观看| 亚洲av乱码一区二区三区| 精品免费久久久久久成人影院| 青青草97国产精品免费观看| 国产A在亚洲线播放| www视频在线观看免费| 亚洲国产AV一区二区三区四区 | 久久久久久精品免费免费自慰| 亚洲女人初试黑人巨高清| 一二三四在线观看免费高清中文在线观看| 性xxxx黑人与亚洲| 国产国产人免费人成免费视频| 又黄又大的激情视频在线观看免费视频社区在线 | 精品亚洲国产成AV人片传媒| 成年黄网站色大免费全看| 亚洲色大成WWW亚洲女子| 亚洲伊人久久综合影院| 亚洲色爱图小说专区| 日本免费一区二区三区| 亚洲精品亚洲人成在线麻豆| 久久99九九国产免费看小说| 色天使亚洲综合一区二区| 亚洲人成影院在线无码按摩店| 成人浮力影院免费看| 亚州**色毛片免费观看| 亚洲电影一区二区| 国产jizzjizz免费视频|