`

浅谈spi机制

 
阅读更多

  • 看到公司的项目代码中,在META-INF下service中定义了一些文件。文件名都是以全限定类名的方式命名的,而且没每个文件里的内容也是一堆全限定类名的值。搞不懂这些是什么用途,遂百度了一下


  • 看到了一篇介绍java中spi的博客链接,该博客中对于java的spi机制做了一些介绍,博客链接附上:点击打开链接
  • 传统的应用中,我们对于一个接口有多个实现类。每一个实现类我们在使用的时候,都是动态去调用的。如果是基于java的spi,我们可以通过在工程的META-INF的service文件夹下创建基于接口的全限定类名的文件,文件内容是对于这个接口提供的多个实现类,内容的格式是一个实现类的全限定类名为一行。

下面通过一个具体的案例来说明spi的实现方式(官方的文档里,对于serviceloader的讲解里有一个具体的例子。):

  1. 首先我们定义一个接口类 com.example.CodeSet,该类中定义了一组针对于某种协议的编码解码的接口方法:
     
     public abstract Encoder getEncoder(String encodingName);
     public abstract Decoder getDecoder(String encodingName);

    每个方法都根据提供的编码返回一个特定的对象,如果该方法不支持该编码格式则返回null
  2. 我们再定义一个实现类com.example.impl.StandardCodecs,它实现了接口CodeSet中定义的方法
  3. 我们在工程中创建如下格式的文件META-INF/services/com.example.CodecSet,其中com.example.CodecSet是一个文件名(该文件是基于接口的全限定类名命名的)
  4. 我们在CodeSet类,初始化的时候创建和保存一个单一的service instance:
    private static ServiceLoader<CodecSet>  codecSetLoader = ServiceLoader.load(CodecSet.class);
  5. 定义了一个静态工厂方法,根据提供的编码名字,去迭代每一个方法的具体实现者,返回相关的编码和解码对象:
    public static Encoder getEncoder(String encodingName) {
         for (CodecSet cp : codecSetLoader) {
             Encoder enc = cp.getEncoder(encodingName);
             if (enc != null)
                 return enc;
         }
         return null;
     }
    至此对于spi的一个实现的,就大功告成啦!!!
附上项目结构:

版权声明:本文为博主原创文章,未经博主允许不得转载。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics