Java SPI机制

有这样的一个应用场景,在某个JAR包内,有一个接口IA,然后有3个IA接口的具体实现类,分别是AIA,BIA,CIA。

那么如果在该JAR包内其他的类中使用接口IA的时候,硬编码IA对象对应的具体实现类,就会导致非常不灵活。这就是SPI机制产生的场景由来。


一、SPI机制概念
SPI的全称是Service Provider Interface。

简单来说,SPI机制提供了一个表达接口和其具体实现类之间的绑定关系的方案。具体是在JAR包的"META-INF/services/"目录下建立一个文件,文件名是接口的全限定名,文件的内容可以有多行,每行都是该接口对应的具体实现类的全限定名。


二、使用例子
2.1、 commons-logging中的例子

在commons-logging:commons-logging:1.1包中有个LogFactory抽象类(全限定名是"org.apache.commons.logging.LogFactory"),在其中有个静态方法

public static LogFactory getFactory() throws LogConfigurationException

用于获取一个默认的LogFactory实例。


在该方法中,有一段Java代码片段如下:
[java]  view plain  copy
  1. if(factory == null) {  
  2.               
  3.                     InputStream names1 = getResourceAsStream(contextClassLoader, "META-INF/services/org.apache.commons.logging.LogFactory");  
  4.                     if(names1 != null) {  
  5.                         BufferedReader name;  
  6.                         try {  
  7.                             name = new BufferedReader(new InputStreamReader(names1, "UTF-8"));  
  8.                         } catch (UnsupportedEncodingException var7) {  
  9.                             name = new BufferedReader(new InputStreamReader(names1));  
  10.                         }  
  11.     value = name.readLine();  
  12.                         name.close();  
  13.                         
  14.                             factory = newFactory(value, baseClassLoader, contextClassLoader);  
  15.                         }  
  16.                     } 
  17.                 } catch (Exception var8) {  
  18.                     
  19.                 }  
  20. }  
这段代码的意思就是说使用SPI机制,在Jar包的"META-INF/services/"目录下查找一个文件名为"org.apache.commons.logging.LogFactory"的文件,在文件中可以配置默认要使用的LogFactory具体实现类的全限定名。
2.2、自己的例子

现在有以下类层次结构


IA的内容如下:

[java]  view plain  copy
  1. package spi;  
  2.   
  3. public interface IA {  
  4.     void doIt();  
  5. }  

AIA的内容如下:

[java]  view plain  copy
  1. package spi;  
  2.   
  3. public class AIA implements IA {  
  4.     public void doIt() {  
  5.         System.out.println("doIt In AIA");  
  6.     }  
  7. }  

BIA的内容如下:

[java]  view plain  copy
  1. package spi;  
  2.   
  3. public class BIA implements IA {  
  4.     public void doIt() {  
  5.         System.out.println("doIt In BIA");  
  6.     }  
  7. }  

CIA的内容如下:

[java]  view plain  copy
  1. package spi;  
  2.   
  3. public class CIA implements IA {  
  4.     public void doIt() {  
  5.         System.out.println("doIt In CIA");  
  6.     }  
  7. }  

Main的内容如下:
[java]  view plain  copy
  1. package spi;  
  2.   
  3. import java.util.Iterator;  
  4. import java.util.ServiceLoader;  
  5.   
  6. public class Main {  
  7.     public static void main(String[] args) {  
  8.         ServiceLoader<IA> spiLoader = ServiceLoader.load(IA.class);  
  9.         Iterator<IA> iaIterator = spiLoader.iterator();  
  10.         // Iterator iaIterator = sun.misc.Service.providers(SPIService.class); 第二种实现
  11.         while (iaIterator.hasNext()) {  
  12.             iaIterator.next().doIt();  
  13.         }  
  14.     }  
  15. }  
在META-INF/services/spi.IA文件中的内容如下:
[plain]  view plain  copy
  1. spi.AIA  
  2. spi.BIA  
  3. spi.CIA  

运行spi.Main,可以发现输出结果如下:


参考文献:

[1]http://singleant.iteye.com/blog/1497259

[2]http://blog.csdn.NET/fenglibing/article/details/7083071

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值