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 @   zhenjingcool  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示