Java 類加載 ——處理同一個類多個版本

這文章主要讓你們在開發的時候可以加載不一樣版本類型的class。html

問題

在不少開發的時候,咱們須要到某個jar包的某個功能,或因爲升級,或其餘緣由,並不老是向後兼容的,這時候咱們就應該須要支持多個不一樣版本的庫。 使用java自帶的的加載器,並不能作到這個要求,java自帶的 "loadClass"只加載一次,以後返回的就是類的引用了。java

解決辦法

使用其餘的 ClassLoader 來加載所需jar; 下面是兩種實現方法:ide

1.使用 URLClassLoader

URLClassLoader 這個類容許你經過URL加載jar或者爲你的類指定一個具體的目錄this

example:url

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)會首先要求從他們的類中加載,你這裏須要自定一個類處理器來指定路徑,知足你的特殊需求。 下面是一個自定義類加載器的示例:spa

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);
        }
    }
}
相關文章
相關標籤/搜索