本文包括:
一.为什么需要自定义类加载器
二.如何自定义类加载器
三.自定义类加载器例子
一.为什么需要自定义类加载器
默认的类加载器只知道如何从本地系统加载类。如果我们的程序只是在本机跑的话,一般来说默认加载器可以应付。但是如果我们需要加载远程服务器的类,或者说加载网络上的,不是本机上的类的时候,就需要到自定义类加载器。
二.如何自定义类加载器
自定义类加载器可以选择继承ClassLoader类,重写里面的方法来实现。里面有三个重要的方法,一个是loadClass()方法,一个是findClass()方法,一个是defineClass()方法。
对于loadClass(String name,Boolean resolve)方法:不推荐重写,因为loadClass()方法做的工作主要为实现双亲委托模型,我们重写的话可能会破坏该模型,并且也增加自己的开发难度。
对于defineClass(String name,byte[] b,int off,int len)方法,主要用于将原始字节转换为Class对象,也不需要我们重写。
对于findClass(String name)方法,根据名称来查找类。把.class文件的内容放入一个byte[]数组中,供defineClass()方法使用。一般我们就重写这个方法。在这个方法中,我们重新定义从哪里,怎么样读取文件内容。这样我们就可以把从本机上改为从网络上得到类,从而实现自定义类加载器。
总而言之:1.继承ClassLoader类。2.重写findClass(String name)方法。 3.在这个方法里面我们重新定义从哪里,怎么读取文件内容到byte[]数组中,供defineClass()使用。
三.自定义类加载器例子
- public class Sample{
- public int v1 = 1;
- public Sample(){
- System.out.println(“Sample is load by :” + this.getClass().getClassLoader());
- }
- }
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.InputStream;
- public class MyClassLoader extends ClassLoader{
- private String name;
- private String path = ”d:\\”;
- private final String fileType = ”.class”;
- public MyClassLoader(String name){
- super();
- this.name = name;
- }
- public MyClassLoader(ClassLoader parent, String name){
- super(parent);
- this.name = name;
- }
- @Override
- public String toString(){return this.name;}
- public String getName(){return name;}
- public void setName(String name){this.name = name;}
- public String getPath(){return path;}
- public void setPath(String path){this.path = path;}
- public String getFileType(){return fileType;}
- protected Class<?> findClass(String name) throws ClassNotFoundException{
- byte[] data = this.loadClassData(name);
- return this.defineClass(name, data, 0, data.length);
- }
- private byte[] loadClassData(String name){
- InputStream is = null;
- byte[] data = null;
- ByteArrayOutputStream baos = null;
- try{
- this.name = this.name.replace(“.”, ”\\”);
- is = new FileInputStream(new File(path + name + fileType));
- baos = new ByteArrayOutputStream();
- int ch = 0;
- while (-1 != (ch = is.read())){
- baos.write(ch);
- }
- data = baos.toByteArray();
- }catch (Exception e){
- e.printStackTrace();
- }finally{
- try{
- is.close();
- baos.close();
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- return data;
- }
- public static void showClassLoader(ClassLoader loader) throws Exception{
- Class clazz = loader.loadClass(“Sample”);
- Object object = clazz.newInstance();
- }
- public static void main(String[] args) throws Exception{
- MyClassLoader loader1 = new MyClassLoader(“loader1″);
- loader1.setPath(“d:\\loader1\\”);
- MyClassLoader loader2 = new MyClassLoader(loader1, ”loader2″);
- loader2.setPath(“d:\\loader2\\”);
- MyClassLoader loader3 = new MyClassLoader(null, ”loader3″);
- loader3.setPath(“d:\\loader3\\”);
- showClassLoader(loader2);
- showClassLoader(loader3);
- }
- }
1.继承ClassLoader。
2.重写findClass()。
3.在findClass()方法里面我们重新定义从哪里,怎么读取文件内容到byte[]数组中,供defineClass()使用。
四.参考