专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

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()得到被代理对象的类名。再根据被代理类名和方法名得到拦截链,也即通知链。如下所示:

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/…

文章永久链接:https://tech.souyunku.com/41189

未经允许不得转载:搜云库技术团队 » JdkDynamicAopProxy实现AOP

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们