设为首页 加入收藏

TOP

Java动态代理深入解析(二)
2017-02-08 08:16:41 】 浏览:371
Tags:Java 动态 代理 深入 解析
? ? ? ? ? ? ? ? ? ? ? InvocationHandler h)
? ? ? ? throws IllegalArgumentException
? ? {
? ? ? ? if (h == null) {
? ? ? ? ? ? throw new NullPointerException();
? ? ? ? }


? ? ? ? /*
? ? ? ? * Look up or generate the designated proxy class.
? ? ? ? */
? ? ? ? Class cl = getProxyClass(loader, interfaces);  //获取代理类的Class


? ? ? ? /*
? ? ? ? * Invoke its constructor with the designated invocation handler.
? ? ? ? */
? ? ? ? try {
? ? ? ? ? ? Constructor cons = cl.getConstructor(constructorParams);  //constructorParams是写死的:{ InvocationHandler.class },上边返回的代理类Class一定是extends Proxy的,而Proxy有一个参数为InvocationHandler的构造函数
? ? ? ? ? ? return cons.newInstance(new Object[] { h });  //这里通过构造函数将我们自己定义的InvocationHandler的子类传到代理类的实例里,当我们调用代理类的任何方法时,实际上都会调用我们定义的InvocationHandler子类重写的invoke()函数
? ? ? ? } catch (NoSuchMethodException e) {
? ? ? ? ? ? throw new InternalError(e.toString());
? ? ? ? } catch (IllegalAccessException e) {
? ? ? ? ? ? throw new InternalError(e.toString());
? ? ? ? } catch (InstantiationException e) {
? ? ? ? ? ? throw new InternalError(e.toString());
? ? ? ? } catch (InvocationTargetException e) {
? ? ? ? ? ? throw new InternalError(e.toString());
? ? ? ? }
? ? }


上面的 Class cl = getProxyClass(loader, interfaces);? 调用的getProxyClass方法:


public static Class getProxyClass(ClassLoader loader,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Class... interfaces)
? ? ? ? throws IllegalArgumentException
? ? {
? ? ? ? if (interfaces.length > 65535) {  //因为在class文件中,一个类保存的接口数量是用2个字节来表示的,因此java中一个类最多可以实现65535个接口
? ? ? ? ? ? throw new IllegalArgumentException("interface limit exceeded");
? ? ? ? }


? ? ? ? Class proxyClass = null;


? ? ? ? /* collect interface names to use as key for proxy class cache */
? ? ? ? String[] interfaceNames = new String[interfaces.length];


? ? ? ? // for detecting duplicates
? ? ? ? Set> interfaceSet = new HashSet<>();
     //验证interfaces里的接口是否能被类加载器加载,是否是接口,是否有重复的 
? ? ? ? for (int i = 0; i < interfaces.length; i++) {
? ? ? ? ? ? /*
? ? ? ? ? ? * Verify that the class loader resolves the name of this
? ? ? ? ? ? * interface to the same Class object.
? ? ? ? ? ? */
? ? ? ? ? ? String interfaceName = interfaces[i].getName();
? ? ? ? ? ? Class interfaceClass = null;
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? interfaceClass = Class.forName(interfaceName, false, loader);
? ? ? ? ? ? } catch (ClassNotFoundException e) {
? ? ? ? ? ? }
? ? ? ? ? ? if (interfaceClass != interfaces[i]) {
? ? ? ? ? ? ? ? throw new IllegalArgumentException(
? ? ? ? ? ? ? ? ? ? interfaces[i] + " is not visible from class loader");
? ? ? ? ? ? }


? ? ? ? ? ? /*
? ? ? ? ? ? * Verify that the Class object actually represents an
? ? ? ? ? ? * interface.
? ? ? ? ? ? */
? ? ? ? ? ? if (!interfaceClass.isInterface()) {
? ? ? ? ? ? ? ? throw new IllegalArgumentException(
? ? ? ? ? ? ? ? ? ? interfaceClass.getName() + " is not an interface");
? ? ? ? ? ? }


? ? ? ? ? ? /*
? ? ? ? ? ? * Verify that this interface is not a duplicate.
? ? ? ? ? ? */
? ? ? ? ? ? if (interfaceSet.contains(interfaceClass)) {
? ? ? ? ? ? ? ? throw new IllegalArgumentException(
? ? ? ? ? ? ? ? ? ? "repeated interface: " + interfaceClass.getName());
? ? ? ? ? ? }
? ? ? ? ? ? interfaceSet.add(interfaceClass);


? ? ? ? ? ? interfaceNames[i] = interfaceName;
? ? ? ? }


? ? ? ? /*
? ? ? ? * Using string representations of the proxy interfaces as
? ? ? ? * keys in the proxy class cache (instead of their Class
? ? ? ? * objects) is sufficient because we require the proxy
? ? ? ? * interfaces to be resolvable by name through the supplied
? ? ? ? * class loader, and it has the advantage that using a string
? ? ? ? * representation of a class makes for an implicit weak
? ? ? ? * reference to the class.
? ? ? ? */
? ? ? ? List key = Arrays.asList(interfaceNames);  //使用interfaces列表作为key缓存在cache里,也就是实现了相同interfaces的代理类只会创建加载一次


? ? ? ? /*
?

首页 上一页 1 2 3 4 5 下一页 尾页 2/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇从JVM的角度来看单例模式 下一篇Java虚拟机字节码执行引擎

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目