java类加载器不同导致SPI 报错 not a subtype

如下图
在这里插入图片描述
整段代码如下,当注释掉myThread.setContextClassLoader(myClassLoader);后才正常运行

package com.hotload;


import java.util.ServiceLoader;

class MyThread extends Thread{
    
    
    @Override
    public void run() {
    
    
        try{
    
    
            ServiceLoader<A> serviceLoader = ServiceLoader.load(A.class);
            A a = serviceLoader.iterator().next();
            a.say();
        } catch (Exception e){
    
    

        }
    }
}

/**
 * @Author mubi
 * @Date 2021/9/25 15:29
 */
public class Application {
    
    

    public static void main(String[] args) throws Exception {
    
    
        String rootPath = "/Users/mubi/git_workspace/java8/java8-api/src/main/java";
        MyComOtherClassLoader myClassLoader = new MyComOtherClassLoader();
        myClassLoader.path = rootPath;

        MyThread myThread = new MyThread();
        myThread.setContextClassLoader(myClassLoader);
        myThread.start();
    }


}

要知道错误,首先要理解java spi,serviceload是用线程上线文加载器的,我们debug到报错代码:接口A的类加载器和接口A的实现类Aimp1的类加载器是不同的,因为设置了线程上线文:
在这里插入图片描述
在这里插入图片描述


当代码改成如下后正常运行

package com.hotload;


import java.lang.reflect.Method;
import java.util.ServiceLoader;

class MyThread extends Thread{
    
    
    @Override
    public void run() {
    
    
        try {
    
    
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            Class clazzA = cl.loadClass("com.hotload.A");

            ServiceLoader<A> serviceLoader = ServiceLoader.load(clazzA);
            Object aimp1 = serviceLoader.iterator().next();

            Method method = aimp1.getClass().getMethod("say");
            method.invoke(aimp1);

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

/**
 * @Author mubi
 * @Date 2021/9/25 15:29
 */
public class Application {
    
    

    public static void main(String[] args) throws Exception {
    
    
        String rootPath = "/Users/mubi/git_workspace/java8/java8-api/src/main/java";
        MyComOtherClassLoader myClassLoader = new MyComOtherClassLoader();
        myClassLoader.path = rootPath;

        MyThread myThread = new MyThread();
        myThread.setContextClassLoader(myClassLoader);
        myThread.start();
    }


}

在这里插入图片描述

debug 查看如下(java.util.ServiceLoade的 375行 可以走完,不再fail了)
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_26437925/article/details/120473343