spi       

spi

JDK中,基于SPI的思想,提供了默认具体的实现,ServiceLoader。利用JDK自带的ServiceLoader,可以轻松实现面向服务的注册与发现,完成服务提供与使用的解耦

服务注册在META-INF/services文件夹下,通过serviceLoader发现META-INF下的服务。

由于应用面向接口编程,修改服务实现也不影响应用

从第三方包的META-INF/services/底下找类名,找到后初始化类,然后放入providers里

image-20191203140311725

public class CustomServiceLoader {

    public static final String MAPPING_CONFIG_PREFIX = "META-INF/services";

    public static <S> List<S> loade(Class<S> service) throws Exception{
        String mappingConfigFile = MAPPING_CONFIG_PREFIX + "/" + service.getName() ;
        //由于一个接口的实现类可能存在多个jar包中的META-INF目录下,所以下面使用getResources返回一个URL数组
        Enumeration<URL> configFileUrls =  CustomServiceLoader.class.getClassLoader().getResources(mappingConfigFile);
        if(configFileUrls == null){
            return null ;
        }
        List<S> services = new LinkedList<S>();
        while(configFileUrls.hasMoreElements()){
            URL configFileUrl = configFileUrls.nextElement();
            String configContent = IOUtils.toString(configFileUrl.openStream());
            String[] serviceNames = configContent.split("\n");
            for(String serviceName : serviceNames){
                Class serviceClass = CustomServiceLoader.class.getClassLoader().loadClass(serviceName);
                Object serviceInstance = serviceClass.newInstance();
                services.add((S)serviceInstance);
            }
        }
        return services ;
    }

}

reference

https://cxis.me/2017/04/17/Java%E4%B8%ADSPI%E6%9C%BA%E5%88%B6%E6%B7%B1%E5%85%A5%E5%8F%8A%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/

https://juejin.im/post/5d2db85d6fb9a07ea7134408

https://blog.csdn.net/is_zhoufeng/article/details/50722440