JDK动态代理

这里我写下截图里面的接口方法 JDK动态代理

 

JDK动态代理

JDK动态代理

这就是为啥写这骗文章的原因,也是一时兴起 见谅见谅JDK动态代理

JDK动态代理

这里就是动态生成了TypeServiceImpl这个类的代理对象,

JDK动态代理

$proxy36就是typeServiceImpl这个类的代理对象

 

JDK动态代理

 

 

 

 

JDK动态代理

 

args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。基本类型的参数被包装在适当基本包装器类(如 java.lang.Integer 或 java.lang.Boolean)的实例中。 

JDK动态代理

 

 

  下面我们来分析一下, jdk底层到底搞了啥就生成了代理类: 
首先我们从获取代理类的方法中的Proxy.newProxyInstance

 public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread()
                .getContextClassLoader(), target.getClass().getInterfaces(),
                this);
    }

点进去, 可以在Proxy 中看到该静态方法的签名:

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
1
2
3
4
该方法的注释:

Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.返回一个特定接口的代理类的实例, 代理类对象可以分发method调用到专门的调用处理器。
1
待会儿就能理解这句话的含义了。根据javaDoc 得出: 
第一个参数为一个类加载器, 就是指定一个类加载器来加载所生成的代理类的字节码而已。 
第二个参数为代理类要去实现的接口 
第三个参数就是我们所定义的invocation handler 我们毕竟刚才传递的是this 嘛 
再看整个方法里面的核心逻辑(删除部分校验逻辑):

  @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);
    //接口克隆了一份
        final Class<?>[] intfs = interfaces.clone();

        /*
         * Look up or generate the designated proxy class.
         * 查询或着生成指定的代理类, 之所以查询是因为, 之前曾经生成
         * 的代理类可能被缓存了。 在这里只是生成了代理类class对象
         * 而已
         */
        Class<?> cl = getProxyClass0(loader, intfs);
        //在这里根据class对象拿到代理类构造方法
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            if (!Modifier.isPublic(cl.getModifiers())) {
                AccessController.doPrivileged(new PrivilegedAction<Void>() {
                    public Void run() {
                        cons.setAccessible(true);
                        return null;
                    }
                });
            }
    //这里真正的创建了 一个代理对象的实例, 
    //我们留一个疑问, 为什么传过去一个包含h的数组???
            return cons.newInstance(new Object[]{h});
        } catch (IllegalAccessException|InstantiationException e) {
          。。。。。
    }JDK动态代理

其中newInstance只是调用Constructor.newInstance来构造响应的代理类的实例

我们接下来把getProxyClass0() 方法逻辑拉出来

  private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }


        return proxyClassCache.get(loader, interfaces);
    }

可以看到Cache字眼了, 如果缓存中存在代理类, 直接从Cache取出, 否则生成并缓存。这里有意思的是如何进行的缓存? 如何判断的代理类是否是同一个?

JDK动态代理