黑马程序员------自定义类加载器总结和proxy代理的总结

来源:互联网 发布:冒充家长打电话软件 编辑:程序博客网 时间:2024/05/04 20:23
---------------------- android培训、java培训、期待与您交流! ----------------------

一:自定义类加载器

1:自定义类加载器必须继承抽象类ClassLoader

ClassLoader 类使用委托模型来搜索类和资源。每个 ClassLoader 实例都有一个相关的父类加载器。需要查找类或资源时,ClassLoader 实例会在试图亲自查找类或资源之前,将搜索类或资源的任务委托给其父类加载器。虚拟机的内置类加载器(称为 "bootstrap class loader")本身没有父类加载器,但是可以将它用作ClassLoader 实例的父类加载器。

应用程序需要实现 ClassLoader 的子类,以扩展 Java 虚拟机动态加载类的方式。

2:loadClass方法与findClass方法

loadClass方法采用类加载器的委托机制进行类的加载,当父类及以上类没找到需要加载的类时,会调用自身的findClass()方法来进行类的加载。因此,自定义类加载器需要在不改变类加载器的委托机制的前提下覆盖findClass方法。

3:defineClass方法

defineClass 方法将一个 byte 数组转换为 Class 类的实例。在findClass方法类内部会把loadClassData方法加载进来的class文件的二进制数据转换成Class实例字节码。

 

二:java.lang.reflect 包中Proxy代理类总结

Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。动态代理类是一个实现在创建类时在运行时指定的接口列表的类。代理接口 是代理类实现的一个接口。代理实例是代理类的一个实例。每个代理实例都有一个关联的调用处理程序对象,它可以实现接口InvocationHandler。通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的Invoke 方法,并传递代理实例、识别调用方法的 java.lang.reflect.Method 对象以及包含参数的Object 类型的数组。调用处理程序以适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。

1:通过Proxy的静态方法getProxyClass得到象征动态类的Class实例
通常用接口相同的类加载器,比如接口用Collection,类加载器用Collection.class.getClassLoader()
getProxyClass函数声明:
         public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces)
返回代理类的 java.lang.Class 对象,并向其提供类加载器和接口数组。该代理类将由指定的类加载器定义,并将实现提供的所有接口。如果类加载器已经定义了具有相同排列接口的代理类,那么现有的代理类将被返回;否则,类加载器将动态生成并定义这些接口的代理类。
2:通过反射获取动态类中的所有方法
例如:Constructor[] constructors = classProxy1.getConstructors();
             Method[] methods = classProxy1.getMethods();
动态类只有一个构造方法,并且接受一个参数,参数类型是java.lang.reflect.InvocationHandler
$Proxy0 (java.lang.reflect.InvocationHandle)。主要没有无参构造方法。
 
3:创建动态类的实例对象

clazzProxy.newInstance()错误,因为动态类没有无参构造方法,newInstance()方法会去调用无参构造方法。

a: 用发射获得动态类的有参构造方法

Contructor constructor = clazzProxy1.getConstructor(InvocationHandle.class);

 

b:创建InvoctionHandle接口子类

//调用有参构造方法,传递实参,真正参数InvoctionHandle对象,但InvoctionHandle是接口,因此有自己创建InvoctionHandle的实现类。

class MyInvoctionHandle1 implements InvoctionHandle{

         //实现接口的方法,此处最简单实现,默认的

         Public Object invoke(Object proxy, Method method,)

throws  Trowable{

                            retrun  null;

                   }

}

C:调用有参构造方法创建动态类实例,将编写的MyInvoctionHandle1类的实例对象传进去

Collection proxy1 =( Collection) constructor.newInstance(new MyInvoctionHandle1());

 

备注也可以用内部类:

Constructor.newInstance(new InvocationHandle(){

         Public Object invoke(Object proxy, Method method,)

throws  Trowable{

                            retrun  null;

                   }

 });

 

4:通过newProyInstance方法将创建动态类和获取动态类实例结合在一起。

new  Class[] { Collction.class} ,

//此处不能用可变参数,应为可变参数必须位于参数列表最后。

Collction proxy3 = (Collction)Proxy.newProxyInstance(

Collction.class.getClassLoader(),

new  Class[] { Collction.class} ,

new InvocationHandle(){

         ArrayList  target = new ArrayList();ssss

                                              Public Object invoke(Object proxy, Method method,)

throws  Trowable{

         long beginTime = System.currentTimeMillis();

         Object retVal = method.invoke(target, args);

long endTime = System.currentTimeMillis();

System.out.println(method.getName() + “running time” + (endTime - begainTime));

                                                                 retrun  retVal;

                                                                  }

}

                                               );

proxy3.add(“lhm”);

proxy3.add(“lhc”);

--------------------- android培训、java培训、期待与您交流! ----------------------详细请查看:http://edu.csdn.net/heima