JdkDynamicAopProxy實現AOP

代理類是由默認AOP代理工廠DefaultAopProxyFactory中createAopProxy方法產生的。若是代理對象是接口類型,則生成JdkDynamicAopProxy代理。下面來看看這個類

構造器

查看源碼,能夠看到JdkDynamicAopProxy是一個final類,不能被繼承和實現。其實現了AopProxy, InvocationHandler, Serializable接口,以下所示:

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable複製代碼
下面看看JdkDynamicAopProxy 構造器,源碼以下:

public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
  Assert.notNull(config, "AdvisedSupport must not be null");
  if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
    throw new AopConfigException("No advisors and no TargetSource specified");
  }
  this.advised = config;
}複製代碼
從構造器能夠看出,JdkDynamicAopProxy依賴於AdvisedSupport,根據config配置信息建立動態代理對象。代碼中config.getAdvisors()提供的是Advisor數組。

getProxy()

getProxy 方法是實現AopProxy接口,源碼以下:

public Object getProxy() {
        return this.getProxy(ClassUtils.getDefaultClassLoader());
    }

public Object getProxy(ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
        logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
    }
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    this.findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}

private void findDefinedEqualsAndHashCodeMethods(Class<?>[] proxiedInterfaces) {
    Class[] var2 = proxiedInterfaces;
    int var3 = proxiedInterfaces.length;
    for(int var4 = 0; var4 < var3; ++var4) {
        Class<?> proxiedInterface = var2[var4];
        Method[] methods = proxiedInterface.getDeclaredMethods();
        Method[] var7 = methods;
        int var8 = methods.length;
        for(int var9 = 0; var9 < var8; ++var9) {
            Method method = var7[var9];
            if (AopUtils.isEqualsMethod(method)) {
                this.equalsDefined = true;
            }
            if (AopUtils.isHashCodeMethod(method)) {
                this.hashCodeDefined = true;
            }
            if (this.equalsDefined && this.hashCodeDefined) {
                return;
            }
        }
    }
}複製代碼

在建立代理時,既能夠採用默認的類加載器,也能夠指定特定的類加載器。JDK動態代理的代理對象是接口類型,先獲取被代理對象的完整接口、根據指定的類加載器以及實現的調用處理器應用靜態方法Proxy.newProxyInstance建立代理對象。

invoke

上文介紹了InvocationHandler 接口,invoke該接口中惟一一個定義的方法。JdkDynamicAopProxy 是final類而且實現了InvocationHandler 接口,那麼也必然實現了invoke方法,其源碼以下:

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;
    TargetSource targetSource = this.advised.targetSource;
    Class<?> targetClass = null;
    Object target = null;
    Class var10;
    try {
       if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
           Boolean var20 = this.equals(args[0]);
           return var20;
       }
       if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
           Integer var18 = this.hashCode();
           return var18;
       }
       if (method.getDeclaringClass() != DecoratingProxy.class) {
           Object retVal;
           if (!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
                retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
                return retVal;
           }
           if (this.advised.exposeProxy) {
               oldProxy = AopContext.setCurrentProxy(proxy);
               setProxyContext = true;
           }
           target = targetSource.getTarget();
           if (target != null) {
               targetClass = target.getClass();
           }

           List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
           if (chain.isEmpty()) {
               Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
               retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
           } else {
               MethodInvocation invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
               retVal = invocation.proceed();
           }

           Class<?> returnType = method.getReturnType();
           if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
                retVal = proxy;
           } else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
                throw new AopInvocationException("Null return value from advice does not match primitive return type for: " + method);
           }

           Object var13 = retVal;
           return var13;
      }

      var10 = AopProxyUtils.ultimateTargetClass(this.advised);
    finally {
       if (target != null && !targetSource.isStatic()) {
           targetSource.releaseTarget(target);
       }

       if (setProxyContext) {
           AopContext.setCurrentProxy(oldProxy);
       }

   }

   return var10;
}複製代碼

前面只是一些校驗,直接省略,步入重點。經過target = targetSource.getTarget()獲得被代理對象的類名。再根據被代理類名和方法名獲得攔截鏈,也即通知鏈。以下所示:java

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);複製代碼

若是攔截鏈爲空,則直接反射調用被代理方法,不然須要建立代理方法,此代理方法中已經加入附加處理(通知)。以下:

if (chain.isEmpty()) {
    	//處理被代理方法參數
    	Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
    	//反射執行被代理方法
    	retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
    	// 建立代理方法
    	invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
	// 執行代理方法
	retVal = invocation.proceed();
}
複製代碼
1. 若攔截鏈爲空,反射執行被代理方法是調用工具類AopUtils中方法invokeJoinpointUsingReflection實現的,具體以下:

public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args) throws Throwable {
    	// Use reflection to invoke the method.
    	try {
    		ReflectionUtils.makeAccessible(method);
    		return method.invoke(target, args);
    	}
    	catch (InvocationTargetException ex) {
    		// Invoked method threw a checked exception.
		// We must rethrow it. The client won't see the interceptor.
		throw ex.getTargetException();
	}
	catch (IllegalArgumentException ex) {
		throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
				method + "] on target [" + target + "]", ex);
	}
	catch (IllegalAccessException ex) {
		throw new AopInvocationException("Could not access method [" + method + "]", ex);
	}
}複製代碼
2. 若攔截鏈不爲空,建立代理方法是經過ReflectiveMethodInvocation實現的,而後調用proceed()方法執行攔截鏈和被代理方法。ReflectiveMethodInvocation實現了Joinpoint接口,其構造器以下:

protected ReflectiveMethodInvocation( Object proxy, Object target, Method method, Object[] arguments, Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
    	this.proxy = proxy;
    	this.target = target;
    	this.targetClass = targetClass;
    	this.method = BridgeMethodResolver.findBridgedMethod(method);
    	this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
    	this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}複製代碼

ReflectiveMethodInvocation調用proceed方法執行代理,proceed方法是在Joinpoint接口中定義的,ReflectiveMethodInvocation中進行了實現。具體實現以下:

public Object proceed() throws Throwable {
    	// We start with an index of -1 and increment early.
    	if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    		return invokeJoinpoint();
    	}
    	Object interceptorOrInterceptionAdvice =
			this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    	if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
    		// Evaluate dynamic method matcher here: static part will already have
		// been evaluated and found to match.
		InterceptorAndDynamicMethodMatcher dm =
				(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
		if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
			return dm.interceptor.invoke(this);
		}
		else {
			// Dynamic matching failed.
			// Skip this interceptor and invoke the next in the chain.
			return proceed();
		}
	}
	else {
		// It's an interceptor, so we just invoke it: The pointcut will have
		// been evaluated statically before this object was constructed.
		return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
	}
}複製代碼

從上面分析源碼大體能夠了解Spring AOP 動態代理的設計思想,採用類加載器根據接口產生代理方法,代理方法是在原方法的基礎上加上通知鏈,以實現AOP功能。當執行方法時,判斷該方法通知鏈是否爲空,若爲空,則經過反射直接調用原方法;若不爲空,則產生代理方法,執行代理方法。


轉載自:blog.ygingko.top/2017/09/19/…spring

相關文章
相關標籤/搜索