最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java自定義類加載器如何實現(xiàn)類隔離

 更新時間:2022年11月19日 11:27:54   作者:快樂崇拜234  
這篇文章主要介紹了java自定義類加載器如何實現(xiàn)類隔離問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

網(wǎng)上java自定義類加載器很多容易找到,但是都是加載的單個類,如果被加載的類,有引用了其他類怎么辦呢?接下來看一下如何來處理這種情況

有時候一個項目中可能會引用不同版本的第三方依賴,比如筆者在升級hbase系統(tǒng)時,代理層就同時用到了1.X和2.X版本的hbase-client的jar包。

當時是使用的阿里的SOFAArk來實現(xiàn)的。

它的本質就是是喲個類加載來實現(xiàn)的,接下來就通過一個小例子來通過自定義類加載器實現(xiàn)類隔離。

下面實例實現(xiàn)了在同一個應用里加載了兩個類名報名完全相同的Hello 和Dog類:

自定義類加載器

準備

準備工作,在D盤的a,b兩個目錄下準備Hello.class 和 Dog.class 兩個文件,可以使用javac編譯。

//a文件夾:
public class Hello {
    private String name;

    public Hello(String name) {
        this.name = name;
    }

    public void sayHello() {
		Dog d =new Dog();
		d.hi();
        System.out.println("a hello " + name + "  "+ this.getClass().getClassLoader());
    }
}

public class Dog {

    public void hi() {
        System.out.println("a hi ...  "+ this.getClass().getClassLoader());
    }
}


//b文件夾
public class Hello {
    private String name;

    public Hello(String name) {
        this.name = name;
    }

    public void sayHello() {
		Dog d =new Dog();
		d.hi();
        System.out.println("b hello " + name + "  "+ this.getClass().getClassLoader());
    }
}

public class Dog {

    public void hi() {
        System.out.println("b hi ...  "+ this.getClass().getClassLoader());
    }
}

通過URLClassLoader來實現(xiàn)【推薦】

類加載器會主動加載被引用的類。比如類A依賴引用了類B ,則只需要主動加載類A即可,類B會自動加載,而且加載類B的類加載器與類A相同。

/**
 * URLClassLoader
 * 推薦此方法
 */
@Test
public void test0() {
    try {
        System.out.println( this.getClass().getClassLoader());

        URLClassLoader diskLoader = new URLClassLoader(new URL[]{new URL("file:/D:/liubenlong/a/")});//最后面的斜杠需要添加
        URLClassLoader diskLoader1 = new URLClassLoader(new URL[]{new URL("file:/D:/liubenlong/b/")});

        //加載class文件
        Class clz = diskLoader.loadClass("Hello");
        Constructor constructor = clz.getConstructor(String.class);
        Object obj = constructor.newInstance("tom");

        /**
         * 類Hello引用了類Dog,類加載器會主動加載被引用的類。
         * 注意一般是我們使用 URLClassLoader 實現(xiàn)自定義的類加載器。如果使用classLoader,則需要重寫findClass方法來實現(xiàn)類字節(jié)碼的加載
         */
        Method method = clz.getMethod("sayHello", null);
        //通過反射調用Test類的say方法
        method.invoke(obj, null);


        Class clz1 = diskLoader1.loadClass("Hello");
        Constructor constructor1 = clz1.getConstructor(String.class);
        Object obj1 = constructor1.newInstance("cat");

        Method method1 = clz1.getMethod("sayHello", null);
        //通過反射調用Test類的say方法
        method1.invoke(obj1, null);

    } catch (Exception e) {
        e.printStackTrace();
    }
}

輸出

jdk.internal.loader.ClassLoaders$AppClassLoader@1f89ab83
a hi ...  java.net.URLClassLoader@3891771e
a hello tom  java.net.URLClassLoader@3891771e
b hi ...  java.net.URLClassLoader@78ac1102
b hello cat  java.net.URLClassLoader@78ac1102

通過繼承ClassLoader實現(xiàn)

網(wǎng)上說可以自定義類加載器實現(xiàn),接下來我們看一下(jdk11直接忽略,因為編譯不通過,下面是在jdk8版本測試)。

package 自定義類加載器;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;

/**
 * 自定義ClassLoader
 */
public class MyClassLoader extends ClassLoader {
    protected Class<?> findClass(String path, String name) {
        try {
            FileInputStream in = new FileInputStream(path + name + ".class");
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buf = new byte[1024];
            int len = -1;
            while ((len = in.read(buf)) != -1) {
                baos.write(buf, 0, len);
            }
            in.close();
            byte[] classBytes = baos.toByteArray();
            return defineClass(name, classBytes, 0, classBytes.length);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

編寫測試類

package 自定義類加載器;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ClassLoaderTest {

    /**
     * 集成ClassLoader,重寫findClass實現(xiàn)自定義類加載器
     */
    @Test
    public void test1() {
        try {
            MyClassLoader diskLoader = new MyClassLoader();
            MyClassLoader diskLoader1 = new MyClassLoader();

            //依賴的類需要提前加載,不是應該自動加載的嗎?
            diskLoader.findClass("D:\\liubenlong\\a\\", "Dog");
            diskLoader1.findClass("D:\\liubenlong\\b\\", "Dog");

            //加載class文件
            Class clz = diskLoader.findClass("D:\\liubenlong\\a\\", "Hello");
            Constructor constructor = clz.getConstructor(String.class);
            Object obj = constructor.newInstance("tom");

            Method method = clz.getMethod("sayHello", null);
            //通過反射調用Test類的say方法
            method.invoke(obj, null);


            Class clz1 = diskLoader1.findClass("D:\\liubenlong\\b\\", "Hello");
            Constructor constructor1 = clz1.getConstructor(String.class);
            Object obj1 = constructor1.newInstance("cat");

            Method method1 = clz1.getMethod("sayHello", null);
            //通過反射調用Test類的say方法
            method1.invoke(obj1, null);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

運行結果:

a hi ...
a hello tom
b hi ...
b hello cat

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

最新評論

洪雅县| 龙胜| 道孚县| 连云港市| 来宾市| 盐池县| 虎林市| 宜都市| 什邡市| 美姑县| 青海省| 木兰县| 郸城县| 韶山市| 正阳县| 岳西县| 兴城市| 盘锦市| 达拉特旗| 文水县| 石景山区| 富蕴县| 兴海县| 韶关市| 砀山县| 磴口县| 姚安县| 沁阳市| 如皋市| 奎屯市| 双流县| 南丰县| 同江市| 南充市| 调兵山市| 深泽县| 廉江市| 平谷区| 龙门县| 阿勒泰市| 鄢陵县|