Java Spi

  • A+
所属分类:Java

Spi的背景:

1)我们现在的编程主要是接口编程,模块之间不对实现进行硬编码,

2)一旦代码中涉及具体的实现,就违反了可插拔的原则,如果要替换一种实现就需要修改代码。

spi的用处:

为了实现模块装配的时候不写死代码,spi提供了一种服务发现机制,有点类似IOC的思想,将装配的控制权转移到代码外,意思就是你如果在装配的时候有2个实现类,那么你可以通过配置文件来写要加载的实现类。

Spi的缺点:

1)Jdk标准的SPI会一次性实例化扩展点所有的实现,由于是全部加载不管是否有使用到所有很浪费资源

2)没有IOC和AOP的支持

Spi的约定

1) 一个提供者,提供了一个接口并存在多种实现的时候。

2) 一般会在Jar包的META-INF/services/目录下,创建一个接口的路径+接口名称的文件,该文件的内容就是该接口具体的实现类的名称,当外部程序装配该模块的时候就可以通过该jar包META-INF/services/里面的配置文件找到对应的实现类名,并完成模块的注入、装载实例化。(jdk提供了一个工具类来实现查找服务:java.util.ServiceLoader)。

spi的简单例子

接口定义

  1. package spi;
  2. public interface SayHello {

  public void hello();

}

2个实现类

  1. package spi;
  2. public class MingHello implements SayHello{
  3. @Override
  4.  public void hello() {
    System.out.println("您好!我是明");
  }
  5. 
}
  6. package spi;
  7. public class YueHello implements SayHello {
  8. @Override
  9.  public void hello() {
    System.out.println("您好!我是月");
  }
  10. }

META-INF.services下的实现类加载文件

文件名:spi.SayHello

文件内容

spi.MingHello
spi.YueHello

程序入口

  1. package spi;
  2. import java.util.ServiceLoader;
  3. public class MainSpi {
  4.     public static void main(String[] args) {
  5.      ServiceLoader<SayHello> sayHesLoader  = ServiceLoader.load(SayHello.class);
  6.      for(SayHello sayHes:sayHesLoader){
  7.       sayHes.hello();
  8.      }
  9.     }
  10. }

运行Main结果

Java Spi

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: