死磕JDK1.8动态代理原理及源码分析

上一节《设计模式之代理模式》中我们已经对设计模式中的代理模式做了一个简单的介绍,这一节将会对Java的动态的代理原理、源码进行深入的分析(注意:这里分析的是JDK1.8中的动态代理的源码)。篇幅有点长,花了好几天的时间才写完,感觉身体被掏空。。。。。。

一、概述

上节介绍过,Java的动态代理是在运行时动态产生的,其底层是通过反射实现的。Java的动态代理要求目标类必须实现接口,否则无法被代理。Java动态代理中最关键的有两个:

  • InvocationHandler接口:代理类不再实现目标类的接口,而是实现InvocationHandler接口,并且重写其 public Object invoke(Object proxy, Method method, Object[] args)  方法,参数proxy是产生的代理对象,method是要执行的目标类的接口中的方法,args是要执行的方法传入的参数。产生的代理类执行方法时,其实执行的就是invoke方法。
  • Proxy类:Proxy提供了静态方法用于生成代理类, public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h),loader是目标类的类加载器,interfaces是目标类的全部接口,h是InvocationHandler接口的子类的实例。

上节测试代码如下,InvocationHandler是控制代理类的方法执行的,代理类的产生是Proxy.newProxyInstance方法产生的。

public class TestJavaDynamicProxy {
 
	@SuppressWarnings("resource")
	public static void main(String[] args) throws IOException {
		UserHandle target = new UserHandle();
		LogProxyHandle invocationHandler = new LogProxyHandle(target);
		Handle handle = (Handle) Proxy.newProxyInstance(target.getClass()
				.getClassLoader(), target.getClass().getInterfaces(),
				invocationHandler);
		handle.add();
	}
}

二、Proxy.newProxyInstance方法

  1. 可以看到newProxyInstance()方法中主要做了如下几件事:
  2. 对目标接口进行克隆
  3. 权限校验
  4. getProxyClass0(loader, intfs)方法获取代理类class对象,重点
  5. 获取代理类中参数为InvocationHandler.class的构造方法
  6. 执行构造方法返回实例对象
public static Object newProxyInstance(ClassLoader loader,
									  Class<?>[] interfaces,
									  InvocationHandler h)
	throws IllegalArgumentException
{
	Objects.requireNonNull(h);

	//对目标类接口进行克隆
	final Class<?>[] intfs = interfaces.clone();
	final SecurityManager sm = System.getSecurityManager();
	//权限校验
	if (sm != null) {
		checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
	}

	/*
	 * Look up or generate the designated proxy class.
	 */
	 //获取代理类clsss对象(重点)
	Class<?> cl = getProxyClass0(loader, intfs);

	/*
	 * Invoke its constructor with the designated invocation handler.
	 */
	 //使用指定的invocation handler调用代理类的构造函数
	try {
		if (sm != null) {
			checkNewProxyPermission(Reflection.getCallerClass(), cl);
		}

		//获取代理类中参数为InvocationHandler.class的构造方法
		final Constructor<?> cons = cl.getConstructor(constructorParams);
		final InvocationHandler ih = h;
		// 检测构造器是否是Public修饰,如果不是则强行转换为可以访问的
		if (!Modifier.isPublic(cl.getModifiers())) {
			AccessController.doPrivileged(new PrivilegedAction<Void>() {
				public Void run() {
					cons.setAccessible(true);
					return null;
				}
			});
		}
		//执行构造方法,返回代理类实例
		return cons.newInstance(new Object[]{h});
	} catch (IllegalAccessException|InstantiationException e) {
		throw new InternalError(e.toString(), e);
	} catch (InvocationTargetException e) {
		Throwable t = e.getCause();
		if (t instanceof RuntimeException) {
			throw (RuntimeException) t;
		} else {
			throw new InternalError(t.toString(), t);
		}
	} catch (NoSuchMethodException e) {
		throw new InternalError(e.toString(), e);
	}
}

下面我们重点看下getProxyClass0(loader, intfs)方法

三、Proxy.getProxyClass0方法

 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
	//根据类加载器和接口数组,从缓存中获取代理类class对象
	return proxyClassCache.get(loader, interfaces);
}

里面最重要的是这个方法:proxyClassCache.get(loader, interfaces),根据类加载器和接口数组,从proxyClassCache缓存中获取代理类class对象。proxyClassCache是什么呢?proxyClassCache是Proxy类中定义的一个静态成员变量,类型是WeakCache,缓存就是从WeakCache中获取的。

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

四、WeakCache类

WeakCache从字面意思看是虚缓存,缓存(键、子键)->值的映射对。WeakCache<K, P, V>中定义了三个泛型K、P、V:其中K是key也就是键;P是参数,可以通过K和P计算出子键;V是value值。通过proxyClassCache.get(loader, interfaces)方法可知:当前的K是类加载器,P是目标类的接口类数组,V就是要产生的代理类class对象。键和值是弱引用,但子键是强引用的。

强引用(StrongReference)
强引用是使用最普遍的引用。如果一个对象具有强引用,那垃圾回收器绝不会回收它。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会靠随意回收具有强引用的对象来解决内存不足的问题。  强引用其实也就是我们平时A a = new A()这个意思。

弱引用(WeakReference)
在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。弱引用可以和一个引用队列(ReferenceQueue)联合使用,如果在创建WeakReference对象的时候,使用了一个ReferenceQueue对象作为参数提供给WeakReference的构造方法,当弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。ReferenceQueue这个名字也可以看出,它是一个队列,当我们调用它的poll()方法的时候,如果这个队列中不是空队列,那么将返回队列前面的那个Reference对象。

在任何时候,我们都可以调用ReferenceQueue的poll()方法来检查是否有它所关心的非强可及对象被回收。如果队列为空,将返回一个null,否则该方法返回队列中前面的一个Reference对象。利用这个方法,我们可以检查哪个WeakReference所弱引用的对象已经被回收。于是我们可以把这些失去所弱引用的对象的WeakReference对象清除掉。常用的方式为:

WeakReference ref = null;
while ((ref = (CacheKey) q.poll()) != null) {
     // 清除ref
}

具体的关于Java的四种引用类型,可以参考《Java四种引用类型: 强引用、弱引用、软引用、虚引用》

主要成员变量如下:

refQueue:弱引用队列,在这里其中存放的是弱引用CacheKey,CacheKey其实就是对WeakCache中的K键的封装,如果CacheKey被垃圾回收了,则其会进入引用队列,我们通过refQueue.poll()获取到CacheKey,从缓存中删除被垃圾回收掉的CacheKey

map:其类型ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>>,把泛型用这样表示ConcurrentMap<A, ConcurrentMap<B, Supplier<V>>>:A即CacheKey,本例中也就是类加载器;B即subKey子键,是由KeyFactory(subKeyFactory.apply(key, parameter))获得的。

reverseMap:暂时不管

subKeyFactory:Proxy的内部类,子键工厂KeyFactory,其apply(key, parameter)方法计算subKey

valueFactory:Proxy的内部类,value工厂ProxyClassFactory,其public Class<?> apply(ClassLoader loader, Class<?>[] interfaces)生产代理类class对象。

final class WeakCache<K, P, V> {

    //引用队列
    private final ReferenceQueue<K> refQueue
        = new ReferenceQueue<>();
    // the key type is Object for supporting null key
    //key类型为Object,支持null key,这里的null key是指new Object();
    private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map
        = new ConcurrentHashMap<>();
    private final ConcurrentMap<Supplier<V>, Boolean> reverseMap
        = new ConcurrentHashMap<>();
    private final BiFunction<K, P, ?> subKeyFactory;
    private final BiFunction<K, P, V> valueFactory;

   
    public WeakCache(BiFunction<K, P, ?> subKeyFactory,
                     BiFunction<K, P, V> valueFactory) {
        this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
        this.valueFactory = Objects.requireNonNull(valueFactory);
    }

    public V get(K key, P parameter) {
	//省略,后面进行分析
	}
}

五、WeakCache.get方法

public V get(K key, P parameter) {
	Objects.requireNonNull(parameter);

        //清理过期对象
	expungeStaleEntries();

	//缓存key对象CacheKey
	Object cacheKey = CacheKey.valueOf(key, refQueue);

	// lazily install the 2nd level valuesMap for the particular cacheKey
	//通过key:CacheKey对象获取vlaue ConcurrentMap<Object, Supplier<Class<?>>>,泛型Class<?>就是代理类Class对象
	ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
	//如果valuesMap为空
	if (valuesMap == null) {
		//如果cacheKey不存在则放进去一个new的Map,否则返回旧值
		ConcurrentMap<Object, Supplier<V>> oldValuesMap
			= map.putIfAbsent(cacheKey, valuesMap = new ConcurrentHashMap<>());
		//如果旧值map不为空,赋值给valusMap					  
		if (oldValuesMap != null) {
			valuesMap = oldValuesMap;
		}
	}

	// create subKey and retrieve the possible Supplier<V> stored by that
	// subKey from valuesMap
	//通过类加载和接口class数组计算子键subKey,因为我们的目标类只实现了一个接口,所以这里返回的是Key1<接口Class>
	Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
	//根据subKey从valuesMap中获取Supplier<代理类Class>
	Supplier<V> supplier = valuesMap.get(subKey);
	Factory factory = null;

	while (true) {
		//如果从valuesMap中获取的supplier不为空
		if (supplier != null) {
		    // supplier might be a Factory or a CacheValue<V> instance
		    //4,通过get()方法返回代理类class对象
		    V value = supplier.get();
		    if (value != null) {
                        //5,返回代理类class对象
		        return value;
		    }
	        }
		
		// else no supplier in cache
		// or a supplier that returned null (could be a cleared CacheValue
		// or a Factory that wasn't successful in installing the CacheValue)

		// lazily construct a Factory
		//如果factory为空,则new一个Factory对象
		if (factory == null) {
			//1,Factory(实现了Supplier<V>接口):实现值的延迟同步构造并将其安装到缓存中的工厂供应商。      
			factory = new Factory(key, parameter, subKey, valuesMap);
		}

		if (supplier == null) {
			//2,如果subKey不存在则将上面构造的factory对象放入valuesMap,否则返回旧值supplier
			supplier = valuesMap.putIfAbsent(subKey, factory);
			if (supplier == null) {
			  // successfully installed Factory
                         //3,赋值
			  supplier = factory;
			}
			// else retry with winning supplier
			//如果旧值supplier不为空,则继续重试
		} else {
			//从valuesMap中获取的supplier不为空,但是其get返回的代理类Class为空
			//用factory替换supplier
			if (valuesMap.replace(subKey, supplier, factory)) {
				// successfully replaced
				// cleared CacheEntry / unsuccessful Factory
				// with our Factory
				supplier = factory;
			} else {
				// retry with current supplier
				//替换失败,继续重试
				supplier = valuesMap.get(subKey);
			}
		}
	}
}

进来会先执行expungeStaleEntries()方法清理过期对象,这里就是利用弱引用被垃圾回收后进入ReferenceQueue队列的特性,poll()出已经被回收的CacheKey,把它从map中清除,expungeStaleEntries内部实现如下

   private void expungeStaleEntries() {
        CacheKey<K> cacheKey;
        while ((cacheKey = (CacheKey<K>)refQueue.poll()) != null) {
            //清除被垃圾回收的CacheKey
            cacheKey.expungeFrom(map, reverseMap);
        }
    }

while循环里面我在代码中标注了顺序,第一次进来的执行顺序为1,2,3,4,5

步骤1,Factory类是WeakCache的内部类,实现了Supplier<V>接口,其get方法返回代理类对象

步骤2,判断子键是否存在,如果不存在则放入1中构造的factory,并返回null,如果存在则只返回原先存放的Supplier的实现类对象

步骤3,步骤2中返回的是null,将factory赋值给supplier

步骤4,步骤3执行完成后进行下一次while循环,进入步骤4,实际上执行的就是步骤2构造的factory对象的get方法

步骤5,判断4中返回的value如果不为空则直接返回

六、Factory.get

Factory类是WeakCache的内部类,可以操作其成员变量,我们重点关注如下这行代码:其中的valueFactory就是WeakCache中在Proxy中传入的ProxyClassFactory对象,ProxyClassFactory这个类的apply方法是生成代理类的关键所在。

value = Objects.requireNonNull(valueFactory.apply(key, parameter));
public synchronized V get() { // serialize access
	// re-check
	Supplier<V> supplier = valuesMap.get(subKey);
	//重复校验是否被修改过
	if (supplier != this) {
		// something changed while we were waiting:
		// might be that we were replaced by a CacheValue
		// or were removed because of failure ->
		// return null to signal WeakCache.get() to retry
		// the loop
		return null;
	}
	// else still us (supplier == this)

	// create new value
	V value = null;
	try {
		//valueFactory(ProxyClassFactory)的apply方法,创建代理类
		value = Objects.requireNonNull(valueFactory.apply(key, parameter));
	} finally {
		if (value == null) { // remove us on failure
			valuesMap.remove(subKey, this);
		}
	}
	// the only path to reach here is with non-null value
	//判断生成的value是否不为空
	assert value != null;

	// wrap value with CacheValue (WeakReference)
	//用CacheValue(实现了Supplier接口)包装value
	CacheValue<V> cacheValue = new CacheValue<>(value);

	// try replacing us with CacheValue (this should always succeed)
	//用cacheVaule替换supplier
	if (valuesMap.replace(subKey, this, cacheValue)) {
		// put also in reverseMap
		reverseMap.put(cacheValue, Boolean.TRUE);
	} else {
		throw new AssertionError("Should not reach here");
	}

	// successfully replaced us with new CacheValue -> return the value
	// wrapped by it
	return value;
}

七、ProxyClassFactory.apply

该类是Proxy的内部类,其中定义了两个成员变量:所有代理类的前缀$Proxy的字符串,还有一个用于生成唯一代理类名称的下一个数字编号的AtomicLong类型的变量。

在apply方法中判断了接口中如果没有非公共接口,则生成的代理类包名用 com.sun.proxy,

代理类全名,如果没有非公共接口,则proxyName=com.sun.proxy.$Proxy0(1,2,3,4......)

最关键是这行byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags),用于生成代理类class文件。

private static final class ProxyClassFactory
	implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
	// prefix for all proxy class names
	//所有代理类的前缀
	private static final String proxyClassNamePrefix = "$Proxy";

	// next number to use for generation of unique proxy class names
	//用于生成唯一代理类名称的下一个数字编号
	private static final AtomicLong nextUniqueNumber = new AtomicLong();

	@Override
	public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

		Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
		for (Class<?> intf : interfaces) {
			/*
			 * Verify that the class loader resolves the name of this
			 * interface to the same Class object.
			 */
			Class<?> interfaceClass = null;
			try {
				interfaceClass = Class.forName(intf.getName(), false, loader);
			} catch (ClassNotFoundException e) {
			}
			//验证类加载器是否将此接口的名称解析为同一类对象
			if (interfaceClass != intf) {
				throw new IllegalArgumentException(
					intf + " is not visible from class loader");
			}
			/*
			 * Verify that the Class object actually represents an
			 * interface.
			 */
			 //判断interfaceClass是否是接口
			if (!interfaceClass.isInterface()) {
				throw new IllegalArgumentException(
					interfaceClass.getName() + " is not an interface");
			}
			/*
			 * Verify that this interface is not a duplicate.
			 */
			 //验证此接口不是重复的
			if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
				throw new IllegalArgumentException(
					"repeated interface: " + interfaceClass.getName());
			}
		}

		//代理类的包名
		String proxyPkg = null;     // package to define proxy class in
		int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

		/*
		 * Record the package of a non-public proxy interface so that the
		 * proxy class will be defined in the same package.  Verify that
		 * all non-public proxy interfaces are in the same package.
		 */
		 //记录非公共代理接口的包,以便在同一包中定义代理类。验证所有非公共代理接口都在同一个包中
		for (Class<?> intf : interfaces) {
			int flags = intf.getModifiers();
			if (!Modifier.isPublic(flags)) {
				accessFlags = Modifier.FINAL;
				String name = intf.getName();
				int n = name.lastIndexOf('.');
				String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
				if (proxyPkg == null) {
					proxyPkg = pkg;
				} else if (!pkg.equals(proxyPkg)) {
					//目标类的非公共接口不在一个包里面
					throw new IllegalArgumentException(
						"non-public interfaces from different packages");
				}
			}
		}

		if (proxyPkg == null) {
			// if no non-public proxy interfaces, use com.sun.proxy package
			//如果没有非公共接口,则包名用 com.sun.proxy
			proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
		}

		/*
		 * Choose a name for the proxy class to generate.
		 */
		 //代理类名自增序号
		long num = nextUniqueNumber.getAndIncrement();
		//代理类名,如果没有非公共接口,则proxyName=com.sun.proxy.$Proxy0(1,2,3,4......)
		String proxyName = proxyPkg + proxyClassNamePrefix + num;

		/*
		 * Generate the specified proxy class.
		 */
		 //生成代理类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());
		}
	}
}

八、ProxyGenerator.generateProxyClass方法

ProxyGenerator类的关键代码如下, 如果想查看源码的话可以通过Idea工具打开看下,eclipse中是无法打开的,还是Idea这个工具厉害啊,哈哈!这个源码就不继续深究了,感兴趣的话可以自己看看哈。

private static final boolean saveGeneratedFiles = (Boolean)AccessController.doPrivileged(new GetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles")); 这行代码会读取sun.misc.ProxyGenerator.saveGeneratedFiles属性,如果为true,则会写到磁盘上

public class ProxyGenerator {
    //省略了很多成员变量
    private static final String superclassName = "java/lang/reflect/Proxy";
    private static final String handlerFieldName = "h";
    private static final boolean saveGeneratedFiles = (Boolean)AccessController.doPrivileged(new GetBooleanAction("sun.misc.ProxyGenerator.saveGeneratedFiles"));

    public static byte[] generateProxyClass(String var0, Class<?>[] var1) {
        return generateProxyClass(var0, var1, 49);
    }

    public static byte[] generateProxyClass(final String var0, Class<?>[] var1, int var2) {
        ProxyGenerator var3 = new ProxyGenerator(var0, var1, var2);
        final byte[] var4 = var3.generateClassFile();
	//如果为true则将文件写入磁盘
        if (saveGeneratedFiles) {
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    try {
                        int var1 = var0.lastIndexOf(46);
                        Path var2;
                        if (var1 > 0) {
                            Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
                            Files.createDirectories(var3);
                            var2 = var3.resolve(var0.substring(var1 + 1, var0.length()) + ".class");
                        } else {
                            var2 = Paths.get(var0 + ".class");
                        }
		        //写文件
                        Files.write(var2, var4, new OpenOption[0]);
                        return null;
                    } catch (IOException var4x) {
                        throw new InternalError("I/O exception saving generated file: " + var4x);
                    }
                }
            });
        }

        return var4;
    }
}

 八,获取生成的代理类$Proxy0.class文件

第一种方式:System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", true),ProxyGenerator.generateProxyClass方法内部会读取这个变量,如果为true,则会把代理类class文件写到磁盘上,我试了一下没有成功,不知道什么原因。。。。。。

第二种方式:byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Handle.class})生产代理类class字节数组,然后通过文件流写入磁盘,这个是可以正常写入的。

public class TestJavaDynamicProxy {

	@SuppressWarnings("resource")
	public static void main(String[] args) throws IOException {
		UserHandle target = new UserHandle();
		LogProxyHandle invocationHandler = new LogProxyHandle(target);
//		writeProxyClassToHardDisk1();
		Handle handle = (Handle) Proxy.newProxyInstance(target.getClass()
				.getClassLoader(), target.getClass().getInterfaces(),
				invocationHandler);
		handle.add();
		writeProxyClassToHardDisk2();
	}

	/**
	 * 第一种方法,添加这一句是生成代理类的class文件,前提是你需要在工程根目录下创建com/sun/proxy目录
	 */
	public static void writeProxyClassToHardDisk1() {
		 System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", true);
	}

	/**
	 * 第二种方法,获取代理类的字节码,然后通过写文件的方式写到磁盘上
	 */
	public static void writeProxyClassToHardDisk2() {
		byte[] classFile = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Handle.class});
		FileOutputStream out = null;
		try {
			out = new FileOutputStream(TestJavaDynamicProxy.class.getResource("").getPath()+"$Proxy0.class");
			out.write(classFile);
			out.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

我们可以在当前类的.class文件所在目录下看的代理类$Proxy0.class

 然后通过JD-JUI对$Proxy0.class进行反编译,可以看到如下源码(省略了equals,toString,hashCode三个方法):

import com.wkp.designpattern.proxy.dynamic.Handle;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

//代理类继承了Proxy,并实现了我们目标类同样实现的Handle接口
public final class $Proxy0 extends Proxy implements Handle
{
  private static Method m1;
  private static Method m2;
  private static Method m3;
  private static Method m0;
  
  //构造方法传入的就是我们自己写的InvocationHandler接口的实现类LogProxyHandle的实例,
  public $Proxy0(InvocationHandler paramInvocationHandler)
  {
    //调用父类Proxy中的构造方法
    super(paramInvocationHandler);
  }
  //省略了equals,toString,hashCode三个方法
  public final void add()
  {
    try
    {
	  //h是当前代理类的父类Proxy中定义的成员变量,其实就是LogProxyHandle的实例
      this.h.invoke(this, m3, null);
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  static
  {
    try
    {
      //通过反射获取方法
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      m3 = Class.forName("com.wkp.designpattern.proxy.dynamic.Handle").getMethod("add", new Class[0]);
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}

我们可以看下第一步分析时如下的代码,cl.getConstructor(constructorParams)获取的就是$Proxy0类的构造方法,而$Proxy0类的构造方法又会调用Proxy的构造方法,将InvocationHandler的实现类LogProxyHandle的实例引用赋值给Proxy中的成员变量h,所以代理类中的this.h.invoke(this, m3, null)方法的h就是我们实现的LogProxyHandle的实例对象。

protected InvocationHandler h;

protected Proxy(InvocationHandler h) {
	Objects.requireNonNull(h);
	this.h = h;
}
/** parameter types of a proxy class constructor */
private static final Class<?>[] constructorParams =
	{ InvocationHandler.class };

public static Object newProxyInstance(ClassLoader loader,
						Class<?>[] interfaces,
						InvocationHandler h)
        throws IllegalArgumentException
{
    //......
    Class<?> cl = getProxyClass0(loader, intfs);
	//......
	final Constructor<?> cons = cl.getConstructor(constructorParams);
	//......
	return cons.newInstance(new Object[]{h});
}

 

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值