SpringBoot源码解读与原理分析(四)SPI机制

2.4 SPI机制(Service Provider Interface)

  • 问题:依赖倒转原则提到,应该依赖接口而不是实现类,但接口最终要有实现类落地。如果因为业务调整需要替换某个接口的实现类,就不得不改动实现类,也就是修改源码。
  • 解决:SPI机制解决了这个问题。通过一种“服务寻找”的机制,动态地加载接口/抽象类对应的具体实现类。把接口的具体实现类的定义和声明交给了外部化的配置文件。
  • 如下图,一个接口可以有多个实现类,通过SPI机制,可以将一个接口需要创建的实现类的对象都罗列到一个特殊的文件中,SPI机制会依次将这些实现类的对象进行创建并返回。
    SPI设计示意图

2.4.1 JDK原生SPI

简单了解即可,使用范围有限,只能通过接口或抽象类来加载具体的实现类。

1.定义接口+实现类

模拟一套Dao接口的不同数据库访问支持

public interface DemoDao {
   
   
}
public class DemoMysqlDao implements DemoDao {
   
   
}
public class DemoOracleDao implements DemoDao {
   
   
}
2.声明SPI文件

JDK的SPI需要遵循以下规范:

  • 所有定义的SPI文件都必须放在项目的META-INF/services目录下
  • 文件名必须命名为接口或抽象类的全限定名
  • 文件内容为接口或抽象类的具体实现类的全限定名;如果有多个,则每行声明一个具体实现类的全限定名,多个类之间没有分隔符

具体步骤:
(1)在resources目录下创建新目录META-INF/services
(2)新建文件:com.star.springboot.spi.DemoDao
(3)输入文件内容:

com.star.springboot.spi.DemoMysqlDao
com.star.springboot.spi.DemoOracleDao

声明SPI文件

3.测试
public class JdkSpiApplication {
   
   

    public static void main(String[] args) {
   
   
        ServiceLoader<DemoDao> serviceLoader = ServiceLoader.load(DemoDao.class);
        serviceLoader.iterator().forEachRemaining(dao -> {
   
   
            System.out.println(dao);
        });
    }

}

输出结果:

com.star.springboot.spi.DemoMysqlDao@65b3120a
com.star.springboot.spi.DemoOracleDao@6f539caf

控制台成功打印出DemoDao的两个实现类对象,这说明JDK原生的SPI机制已成功使用。

2.4.2 SpringFramework 3.2 的SPI

SpringFramework中的SPI比JDK原生的SPI更高级实用,因为它不仅限于接口或抽象类,而可以是任何一个类、接口或注解
SpringBoot中大量用到SPI机制加载自动配置类和特殊组件等(如@EnableAutoCon

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

维先生d

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值