使用URLClassLoader加载不同Jar包中的相同包名相同类名的类

使用URLClassLoader加载不同Jar包中的相同包名相同类名的类

开发中会遇到这种情况,使用一项功能需要依赖jar,然而一段时间后这些包升级,包名和类名均不变的情况下功能发生变化。旧的jar依然需要使用,而新功能却需要使用新升级的jar。这时如果依赖两个包,使用时会造成冲突。因此需要进行jar隔离。有很多的隔离框架可以使用,如jarlinks。本文将演示通过URLClassLoader加载器来进行隔离的基本方法,而实应用中的的一些隔离框架中也会看到此种方式的使用。

首先原有系统内部依赖version782.jar包,并用到该包中的RequestHead类。而此时又希望用到version713.jar包中的RequestHead类。直接增加maven依赖会产生冲突,这里通过URLClassLoader进行加载。

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import xxx.RequestHead;
import org.apache.commons.codec.binary.Hex;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class ClassLoadTest {

    public static void main(String[] args) throws Exception {
        URL url = new File("/version713.jar").toURI().toURL();
        // 创建URLClassLoader,并设置父加载器为null,这样通过加载器加载
        // 类时就不会通过父加载器去通过classpath中加载version782.jar
        // 中的RequestHead
        URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url}, null);

        // 加载version713.jar包中的RequestHead类
        Class clz = urlClassLoader.loadClass("xxx.RequestHead");
        // 加载序列化工具类,由于要通过反射调用ProtoBufferCore中的方法
        // 而且需要指定Class参数,这个参数需要与ProtoBufferCore使用相同
        // 的类加载器,因此后续加载参数CtripBusinessBean
        Class pb = urlClassLoader.loadClass("xxx.ProtoBufferCore");
        // 加载参数CtripBusinessBean,调用ProtoBufferCore方法时使用
        Class ctripBizBean = urlClassLoader.loadClass("xxx.CtripBusinessBean");

        RequestHead head782 = new RequestHead();
        Object head713 = clz.newInstance();

        Object pbObject = pb.newInstance();

        System.out.println(pbObject);
        System.out.println(JSON.toJSONString(head713, SerializerFeature.WriteNullStringAsEmpty));
        System.out.println(JSON.toJSONString(head782, SerializerFeature.WriteNullStringAsEmpty));

        clz.getField("appId").set(head713,"999111");
        // 这里进行方法调用时,执行参数上文中加载的ctripBizBean,
        // 这样才能保证正确调用
        Method toByteArrayMethod = pb.getMethod("toByteArray",ctripBizBean);
        String hex = Hex.encodeHexString((byte[]) toByteArrayMethod.invoke(pbObject,head713));
        System.out.println(hex);
    }
}

参考

java虚拟机规范5.3节

你可能感兴趣的:(Java)