java的SPI机制

参考https://blog.csdn.net/qq_52423918/article/details/130968307

1 概念

Java SPI(Service Provider Interface)是Java官方提供的一种服务发现机制,它允许在运行时动态地加载实现特定接口的类,而不需要在代码中显式地指定该类,从而实现解耦和灵活性。

2 实现原理

Java SPI 的实现原理基于 Java 类加载机制和反射机制。

这里会用到java.util.ServiceLoader类加载器。当使用 ServiceLoader.load(Class<T> service) 方法加载服务时,会检查 META-INF/services 目录下是否存在以接口全限定名命名的文件。如果存在,则读取文件内容,获取实现该接口的类的全限定名,并通过 Class.forName() 方法加载对应的类。

在加载类之后,ServiceLoader 会通过反射机制创建对应类的实例,并将其缓存起来。

这里涉及到一个懒加载迭代器的思想:
当我们调用 ServiceLoader.load(Class<T> service) 方法时,并不会立即将所有实现了该接口的类都加载进来,而是返回一个懒加载迭代器。
只有在使用迭代器遍历时,才会按需加载对应的类并创建其实例。

3 例子

服务接口ProgrammingLanguageService

public interface ProgrammingLanguageService {
    void study();
}

两个实现类

public class JavaServiceImpl implements ProgrammingLanguageService {
    @Override
    public void study() {
        System.out.println("开始学习java");
    }
}

public class PythonServiceImpl implements ProgrammingLanguageService {
    @Override
    public void study() {
        System.out.println("开始学习python");
    }
}

创建META-INF/services路径和com.demo.szj.ProgrammingLanguageService文件,内容

com.demo.szj.JavaServiceImpl
com.demo.szj.PythonServiceImpl

启动类

public class ServiceLoaderTest {
    public static void main(String[] args) {
        ServiceLoader<ProgrammingLanguageService> serviceLoader = ServiceLoader.load(ProgrammingLanguageService.class);
        Iterator<ProgrammingLanguageService> iterator = serviceLoader.iterator();
        while(iterator.hasNext()) {
            ProgrammingLanguageService service = iterator.next();
            service.study();
        }
    }
}

执行结果

我们看到,虽然我们没有创建这两个服务类,但是通过SPI机制,可以成功创建其实例。

 

posted @ 2024-02-08 16:31  zhenjingcool  阅读(33)  评论(0编辑  收藏  举报