Java 类加载 ——处理同一个类多个版本

这文章主要让大家在开发的时候能够加载不同版本类型的class。

问题

在很多开发的时候,我们需要到某个jar包的某个功能,或由于升级,或其他原因,并不总是向后兼容的,这时候我们就应该需要支持多个不同版本的库。 使用java自带的的加载器,并不能做到这个要求,java自带的 "loadClass"只加载一次,之后返回的就是类的引用了。

解决办法

使用其他的 ClassLoader 来加载所需jar; 下面是两种实现方法:

1.使用 URLClassLoader

URLClassLoader 这个类允许你通过URL加载jar或者为你的类指定一个具体的目录

example:

URLClassLoader clsLoader = URLClassLoader.newInstance(new URL[] {new URL("file:/C://Test/test.jar")});
Class cls = clsLoader.loadClass("test.Main");
Method method = cls.getMethod("main", String[].class);
String[]params = new String[2]; 
method.invoke(null, (Object) params);

2.定义自己的类加载器

在java的类加载器(包括:URLClassLoader)会首先要求从他们的类中加载,你这里需要自定一个类处理器来指定路径,满足你的特殊需求。 下面是一个自定义类加载器的示例:

import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;

public class CustomClassLoader extends ClassLoader 
{
    private ChildClassLoader childClassLoader;

    public CustomClassLoader(List<URL> classpath)
    {
        super(Thread.currentThread().getContextClassLoader());
        URL[] urls = classpath.toArray(new URL[classpath.size()]);
        childClassLoader = new ChildClassLoader( urls, new DetectClass(this.getParent()) );
    }

    @Override
    protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
    {
        try
        {
            return childClassLoader.findClass(name);
        }
        catch( ClassNotFoundException e )
        {
            return super.loadClass(name, resolve);
        }
    }

    private static class ChildClassLoader extends URLClassLoader
    {
        private DetectClass realParent;

        public ChildClassLoader( URL[] urls, DetectClass realParent )
        {
            super(urls, null);
            this.realParent = realParent;
        }

        @Override
        public Class<?> findClass(String name) throws ClassNotFoundException
        {
            try
            {
                Class<?> loaded = super.findLoadedClass(name);
                if( loaded != null )
                    return loaded;
                return super.findClass(name);
            }
            catch( ClassNotFoundException e )
            {
                return realParent.loadClass(name);
            }
        }
    }

    private static class DetectClass extends ClassLoader
    {
        public DetectClass(ClassLoader parent)
        {
            super(parent);
        }

        @Override
        public Class<?> findClass(String name) throws ClassNotFoundException
        {
            return super.findClass(name);
        }
    }
}

你可能感兴趣的:(java,ClassLoader)