Java

SPI

2020-04-14  本文已影响0人  愤怒的老照

背景

最近看到了SPI这个东西,搜了几篇文章有了大概的认识,在这里记录一下。

简介

SPI(Service Provider Interface),是JDK内置的一种 服务提供发现机制,可以用来替换不同的实现,Java中SPI机制主要思想是将装配的控制权移到程序之外,在模块化设计中这个机制尤其重要,其核心思想就是 解耦。

使用场景

其实SPI已经接触过很多次了,只是自己之前没有注意过。JDBC就是使用了SPI机制,JDBC提供连接数据库的接口,由不同的数据库厂商提供各自的连接实现(应该是不提供的话就会失去Java这个大市场吧),我们需要哪个数据库只需要加载对应的服务实现。

Java的SPI机制

Java中已经提供了SPI的约定,当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件,该文件里就是实现该服务接口的具体实现类。当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。也可以使用其它方式。

尝试

实现SPI的方式有很多,正好项目里出现了starter包的使用,所以打算使用starter测试一下


image.png

1、创建maven多模块,包含了api模块、spiA模块、spiB模块和starter模块

public interface IPersonWork {
    public String work();
}
public class PersonAWork implements IPersonWork {
    @Override
    public String work() {
        return "我是A,我来工作了";
    }
}
public class PersonBWork implements IPersonWork {
    @Override
    public String work() {
        return "我是PersonB,我来工作了";
    }
}
@Configuration
@ConditionalOnClass(IPersonWork.class)
public class AutoConfig {

    @ConditionalOnMissingClass({"personAWork"})
    @Bean
    public IPersonWork personBWork() {
        return new PersonBWork();
    }

    @Bean
    public IPersonWork personAWork() {
        return new PersonAWork();
    }
}

2、第三方使用

<dependency>
            <artifactId>com.suhongyan.www.starter</artifactId>
            <groupId>org.example</groupId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
@SpringBootTest
public class Test {

    @Resource
    private IPersonWork personBWork;
    @Autowired
    @org.junit.jupiter.api.Test
    void contextLoads() {
        System.out.println(personBWork.work());
    }
}
我是PersonB,我来工作了

spi的实现没有限制,可以使用starter、使用java的ServiceLoader,也可以在调用方直接做判断。

上一篇 下一篇

猜你喜欢

热点阅读