JDK动态代理原理探究

JDK动态代理原理探究

代理介绍及实现

代理介绍及实现

JDK动态代理源码解析

实现代码:

public class ServiceProxy implements InvocationHandler {
    Object target;

    public ServiceProxy(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("do before.");
        method.invoke(target, args);
        System.out.println("do after");
        return null;
    }

    public Object getTarget() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), this);
    }
}

从上面代码中可以看出,实际生成代理类的是 **Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), this);** 这段。而 invoke(Object proxy, Method method, Object[] args) 是为在生成代理类时利用反射的原理进行调用,所以在newProxyInstance的入参中,传入的是this

查看 newProxyInstance 源码:

    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {

        /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */

        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;
                }
            });
        }
        return cons.newInstance(new Object[]{h});
        ....
    }

我把校验什么的都去除掉,只取关键部分。可以看出实际生成代理类的是:

   /*
    * Look up or generate the designated proxy class.
    */
    Class<?> cl = getProxyClass0(loader, intfs);

在点进去看

    /**
     * Generate a proxy class.  Must call the checkProxyAccess method
     * to perform permission checks before calling this.
     */
    private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);
    }

    /**
     * a cache of proxy classes
     */
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

    // WeakCache 类,
    final class WeakCache<K, P, V> {    
        ...
        // 构造器
        public WeakCache(BiFunction<K, P, ?> subKeyFactory,
                     BiFunction<K, P, V> valueFactory) {
            this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
            this.valueFactory = Objects.requireNonNull(valueFactory);
        }
        ...
    }

上面这段主要是 proxyClassCache 这个缓存,这个缓存什么用?这个缓存主要应该是增加产生代理类的效率的,下次再生成代理类的时候直接通过loader和interfaces去取就行了。那第一次是什么时候存入的那?我们溯回源头:subKeyFactory生成 key值,subKeyFactory通过loader和interfaces生成Key值。
valueFactory 生成代理类,存入缓存中。

看看 ProxyClassFactory 这个类,这个类是个私有的静态内部类

  private static final class ProxyClassFactory
      implements BiFunction<ClassLoader, Class<?>[], Class<?>>
  {
       @Override
      public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

          .....
          /*
           * Choose a name for the proxy class to generate.
           */
          long num = nextUniqueNumber.getAndIncrement();
          String proxyName = proxyPkg + proxyClassNamePrefix + num;

          /*
           * Generate the specified proxy class.
           */
          byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
              proxyName, interfaces, accessFlags);
          try {
              return defineClass0(loader, proxyName,
                                  proxyClassFile, 0, proxyClassFile.length);
          } catch (ClassFormatError e) {
              /*
               * A ClassFormatError here means that (barring bugs in the
               * proxy class generation code) there was some other
               * invalid aspect of the arguments supplied to the proxy
               * class creation (such as virtual machine limitations
               * exceeded).
               */
              throw new IllegalArgumentException(e.toString());
          }
      }
  }

上面代码,去掉一些校验,主要代码呈现出来 **byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);** 这个类就是产生代理类的类。现在主要是看哪里进行调用的

在来看 proxyClassCache 的get方法

public V get(K key, P parameter) {
    ...
    if (supplier != null) {
        // supplier might be a Factory or a CacheValue<V> instance
        V value = supplier.get();
        if (value != null) {
            return value;
        }
    }
    ....
}

private final class Factory implements Supplier<V> {
     @Override
    public synchronized V get() { // serialize access
        ...
        V value = null;
        try {
            value = Objects.requireNonNull(valueFactory.apply(key, parameter));
        } finally {
            if (value == null) { // remove us on failure
                valuesMap.remove(subKey, this);
            }
        }
        ...
        return value;
    }
}         

上面可看出最终调用生成代码的是 Factory#get() 方法 ,而在 proxyClassCache.get 方法中,factory 赋值给了supplier ,supplier使用get方法完成代理类的创建。

有些绕,但是仔细理一下代码就不难看出动态代理的生成过程。

看看代理类是如何完成代理的,我们手动生成动态代理类的.class文件,然后在进行反编译即可发现端倪:


public interface Service {
    void sayHell();
}

/**
 * @program: demo
 * @description:
 * @author: LEMONTREE
 * @create: 2018-08-22 21:16
 */
public class JdkProxy implements InvocationHandler {

    private Object targt;

    public JdkProxy(Object targt) {
        this.targt = targt;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("open...");
        method.invoke(targt, args);
        System.out.println("close..");
        return null;
    }

    public Object getInstance() {
        return Proxy.newProxyInstance(targt.getClass().getClassLoader(),
                targt.getClass().getInterfaces(), this);
    }

}


/**
 * @program: demo
 * @description:
 * @author: LEMONTREE
 * @create: 2018-08-21 23:31
 */
public class Main {
    public static void main(String[] args) throws IOException {
        String proxyName = "com.sun.proxy.$Proxy0.class";
        Service service = new ServiceImpl();
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, service.getClass().getInterfaces(), 17);
        OutputStream out = new FileOutputStream("D:\\$Proxy0");
        InputStream in = new ByteArrayInputStream(proxyClassFile);
        byte[] buff = new byte[1024];
        int len = 0;
        while ((len = in.read(buff))!=-1){
            out.write(buff);
        }
        in.close();
        out.close();
    }
}

$Proxy0.class 文件拖到idea中即可完成反编译,看下代码:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.sun.proxy;

import com.lemontest.test.proxy.Service;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class $Proxy0 extends Proxy implements Service {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }


    public final void sayHell() throws  {
        try {
            super.h.invoke(this, m3, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.lemontest.test.proxy.Service").getMethod("sayHell");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

这里去除了一些公用方法(toString之类的),可以看出:代理类通过h(InvocationHandler,这里是我们传入的JdkProxy),调用JdkProxy的invoke方法

总结

总结一下,简单来说,其实就是 Proxy.newProxyInstance(targt.getClass().getClassLoader(), targt.getClass().getInterfaces(), this); 这个方法生成代理类,生成的代理类的方法都是通过 InvocationHandler 实现类也就是JdkProxy进行包装过(或说代理过)的方法。为什么是JdkProxy的方法?仔细看JdkProxy类,看出,newProxyInstance 方法最后的入参,传了个this进去。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值