Spring的JDK动态代理如何实现的(源码解析)

JDK动态代理的使用方式

首先对于InvocationHandler的创建是最为核心的,可以自定义类实现它。实现后需要重写3个函数:

接下来我们看一下Spring中的JDK代理方式是如何实现的吧。

看源码之前先大致了解一下Spring的JDK创建过程的大致流程

如图:

Spring的JDK动态代理如何实现的(源码解析)

/**
     * 代理对象的配置信息,例如保存了 TargetSource 目标类来源、能够应用于目标类的所有 Advisor
     */
private final AdvisedSupport advised;
public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException {
    Assert.notNull(config, "AdvisedSupport must not be null");
    // config.getAdvisorCount() == 0 没有 Advisor,表示没有任何动作
    if (config.getAdvisorCount() == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) {
        throw new AopConfigException("No advisors and no TargetSource specified");
    }
    this.advised = config;
    // 获取需要代理的接口(目标类实现的接口,会加上 Spring 内部的几个接口,例如 SpringProxy
    this.proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    //判断目标类是否重写了 `equals` 或者 `hashCode` 方法
    // 没有重写在拦截到这两个方法的时候,会调用当前类的实现
    findDefinedEqualsAndHashCodeMethods(this.proxiedInterfaces);
}
@Override
    public Object getProxy() {
    return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
    public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isTraceEnabled()) {
        logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    }
    // 调用 JDK 的 Proxy#newProxyInstance(..) 方法创建代理对象
    // 传入的参数就是当前 ClassLoader 类加载器、需要代理的接口、InvocationHandler 实现类
    return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
@Override
    @Nullable
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object oldProxy = null;
    Boolean setProxyContext = false;
    TargetSource targetSource = this.advised.targetSource;
    Object target = null;
    try {
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            // The target does not implement the equals(Object) method itself.
            return equals(args[0]);
        } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            // The target does not implement the hashCode() method itself.
            return hashCode();
        } else if (method.getDeclaringClass() == DecoratingProxy.class) {
            // There is only getDecoratedClass() declared -> dispatch to proxy config.
            return AopProxyUtils.ultimateTargetClass(this.advised);
        } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                            method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            // Service invocations on ProxyConfig with the proxy config...
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }
        Object retVal;
        if (this.advised.exposeProxy) {
            // Make invocation available if necessary.
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }
        // Get as late as possible to minimize the time we "own" the target,
        // in case it comes from a pool.
        target = targetSource.getTarget();
        Class<?> targetClass = (target != null ? target.getClass() : null);
        // Get the interception chain for this method.
        // 获取当前方法的拦截器链  具体实现是在 DefaultAdvisorChainFactory
        List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        // Check whether we have any advice. If we don't, we can fallback on direct
        // reflective invocation of the target, and avoid creating a MethodInvocation.
        if (chain.isEmpty()) {
            // We can skip creating a MethodInvocation: just invoke the target directly
            // Note that the final invoker must be an InvokerInterceptor so we know it does
            // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        } else {
            // We need to create a method invocation...
            //  将拦截器封装在ReflectiveMethodInvocation,以便于使用其proceed进行链接表用拦截器
            MethodInvocation invocation =
                                    new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // Proceed to the joinpoint through the interceptor chain.
            // 执行拦截器链
            retVal = invocation.proceed();
        }
        // Massage return value if necessary.
        Class<?> returnType = method.getReturnType();
        // 返回结果
        if (retVal != null && retVal == target &&
                            returnType != Object.class && returnType.isInstance(proxy) &&
                            !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            // Special case: it returned "this" and the return type of the method
            // is type-compatible. Note that we can't help if the target sets
            // a reference to itself in another returned object.
            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);
        }
        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            // Must have come from TargetSource.
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}
  • 源码分析从上面的源码可以看出Spring中的 JDKDynamicAopProxy 和我们自定一JDK代理是一样的,也是实现了 InvocationHandler 接口。并且提供了 getProxy 方法创建代理类,重写了 invoke 方法(该方法是一个回调方法)。具体看源码
  • 看源码
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object oldProxy = null;
    Boolean setProxyContext = false;
    TargetSource targetSource = this.advised.targetSource;
    Object target = null;
    try {
        if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
            // The target does not implement the equals(Object) method itself.
            return equals(args[0]);
        } else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
            // The target does not implement the hashCode() method itself.
            return hashCode();
        } else if (method.getDeclaringClass() == DecoratingProxy.class) {
            // There is only getDecoratedClass() declared -> dispatch to proxy config.
            return AopProxyUtils.ultimateTargetClass(this.advised);
        } else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
                            method.getDeclaringClass().isAssignableFrom(Advised.class)) {
            // Service invocations on ProxyConfig with the proxy config...
            return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
        }
        Object retVal;
        if (this.advised.exposeProxy) {
            // Make invocation available if necessary.
            oldProxy = AopContext.setCurrentProxy(proxy);
            setProxyContext = true;
        }
        // Get as late as possible to minimize the time we "own" the target,
        // in case it comes from a pool.
        target = targetSource.getTarget();
        Class<?> targetClass = (target != null ? target.getClass() : null);
        // Get the interception chain for this method.
        // 获取当前方法的拦截器链  具体实现是在 DefaultAdvisorChainFactory
        List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
        // Check whether we have any advice. If we don't, we can fallback on direct
        // reflective invocation of the target, and avoid creating a MethodInvocation.
        if (chain.isEmpty()) {
            // We can skip creating a MethodInvocation: just invoke the target directly
            // Note that the final invoker must be an InvokerInterceptor so we know it does
            // nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
            Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
            retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
        } else {
            // We need to create a method invocation...
            //  将拦截器封装在ReflectiveMethodInvocation,以便于使用其proceed进行链接表用拦截器
            MethodInvocation invocation =
                                    new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
            // Proceed to the joinpoint through the interceptor chain.
            // 执行拦截器链
            retVal = invocation.proceed();
        }
        // Massage return value if necessary.
        Class<?> returnType = method.getReturnType();
        // 返回结果
        if (retVal != null && retVal == target &&
                            returnType != Object.class && returnType.isInstance(proxy) &&
                            !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
            // Special case: it returned "this" and the return type of the method
            // is type-compatible. Note that we can't help if the target sets
            // a reference to itself in another returned object.
            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);
        }
        return retVal;
    }
    finally {
        if (target != null && !targetSource.isStatic()) {
            // Must have come from TargetSource.
            targetSource.releaseTarget(target);
        }
        if (setProxyContext) {
            // Restore old proxy.
            AopContext.setCurrentProxy(oldProxy);
        }
    }
}