作为一个Java工程师,你应该要知道SPI机制

  什么是SPI   

SPI是服务提供者接口的简称,是JDK默认提供的一种将接口和实现类进行分离的机制。这种机制能将接口和实现进行解耦,大大提升系统的可扩展性。

  

SPI机制约定:当一个Jar包需要提供一个接口的实现类时,这个Jar包需要在meta - inf/服务/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该Jar包meta - inf/服务/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。

  

比如下面的列子,   <代码> jcl-over-slf4j 这个Jar包提供了conmon-logging中   <代码> LogFactory 这个接口的实现。

  

  

        作为一个Java工程师,你应该要知道SPI机制   
  图像      

文件中的内容如下:

        作为一个Java工程师,你应该要知道SPI机制   
  

JDK为了方便查找服务的实现,还提供了一个工具类:java.util.ServiceLoader。

        作为一个Java工程师,你应该要知道SPI机制   
  

上面代码中使用   <代码>即便ServiceLoader> LogFactory 实现。

  应用场景   

SPI机制的主要应用有框架扩展和组件的替换等,比如

  
      <李> JDBC接口实现类的运行时加载:我们连接具体的数据库是都需要添加相关的Jar包依赖,但是不需要我们再做任何其他配置,只要将Jar包放到类路径下就行了。这是一个最常见的SPI应用场景。   <李>日志门面加载具体的日志实现类:之前的博客中介绍到,jcl和slf4j等只是日志实现类,Log4j和LOgBack才是具体的日志实现.JCL和slf4j加载日志实现类时也使用了SPI机制,具体请看上面章节中举的列子。   <李>春天中大量使用了SPI:比如对servlet3.0规范对ServletContainerInitializer的实现,自动类型转换类型转换SPI(转炉SPI、格式化器SPI)等李
  自己实现   

下面就一步步从定义接口到提供SPI实现类来演示下SPI机制具体的使用方式。

  

  

  

& lt;前类=癹ava"风格=氨Vそ?10 px 0 px;填充:0 px;空白:pre !重要;自动换行:break-word;位置:相对!重要;“在

  

复制   

的公共接口SaySomething {

  <>以前String 说(String 名称),之前   

}’& lt;/pre>

  

  

  

& lt;前类=癹ava"风格=氨Vそ?10 px 0 px;填充:0 px;空白:pre !重要;自动换行:break-word;位置:相对!重要;“在

  

复制   

  <代码>公共类ASaySomething实现SaySomething {@Override公共字符串(字符串名称)说{返回“嗨,“+名称+“,我…“;;}} & lt;/pre>

  

     
添加完这个目录后,添加一个以   <代码> SaySomething 接口的全限定名为名字的文件,这个文件的内容是你要设置的具体实现类。这边我们就设置实现类为上面的   <代码> ASaySomething>   

  

  

& lt;前类=癹ava"风格=氨Vそ?10 px 0 px;填充:0 px;空白:pre !重要;自动换行:break-word;位置:相对!重要;“在

  

复制   

  <代码>公共静态void main (String [] args) {ServiceLoader装载机=ServiceLoader.load (SaySomething.class);加载程序。forEach(项→{item.say (“csx");});} & lt;/pre>

   API和SPI的比较   

在开发中我们还经常会提到API这个名词、下面也总结下两者的区别:

  
      <李>   

    API(应用程序编程接口)在大多数情况下,都是实现方制定接口并完成对接口的实现,调用方仅仅依赖接口调用,且无权选择不同实现。从使用人员上来说,API直接被应用开发人员使用。

      <李>   

    SPI(服务提供者接口)是调用方来制定接口规范,提供给外部来实现,调用方在调用时则选择自己需要的外部实现。从使用人员上来说,SPI被框架扩展人员使用。

  优缺点   

  

作为一个Java工程师,你应该要知道SPI机制