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 鴻雁 閱讀(265) 評論(0)  編輯  收藏


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


          網站導航:
           
          主站蜘蛛池模板: 竹山县| 德安县| 德江县| 高平市| 昌图县| 德昌县| 洛扎县| 栾城县| 遂昌县| 竹溪县| 郓城县| 湖南省| 灵武市| 共和县| 丹寨县| 滕州市| 满城县| 改则县| 阳信县| 万荣县| 焉耆| 姚安县| 东方市| 临汾市| 永登县| 旌德县| 芒康县| 崇义县| 祁连县| 鄄城县| 永宁县| 武夷山市| 武清区| 胶南市| 麻城市| 布拖县| 庆城县| 竹北市| 万荣县| 阿克| 永春县|