Java SPI机制
2015-07-30 10:19
453 查看
有这样的一个应用场景,在某个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代码片段如下:
这段代码的意思就是说使用SPI机制,在Jar包的"META-INF/services/"目录下查找一个文件名为"org.apache.commons.logging.LogFactory"的文件,在文件中可以配置默认要使用的LogFactory具体实现类的全限定名。
2.2、自己的例子
现在有以下类层次结构
IA的内容如下:
AIA的内容如下:
BIA的内容如下:
CIA的内容如下:
Main的内容如下:
运行spi.Main,可以发现输出结果如下:
参考文献:
[1]http://singleant.iteye.com/blog/1497259
[2]http://blog.csdn.net/fenglibing/article/details/7083071
那么如果在该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代码片段如下:
if(factory == null) { if(isDiagnosticsEnabled()) { logDiagnostic("[LOOKUP] Looking for a resource file of name [META-INF/services/org.apache.commons.logging.LogFactory] to define the LogFactory subclass to use..."); } try { InputStream names1 = getResourceAsStream(contextClassLoader, "META-INF/services/org.apache.commons.logging.LogFactory"); if(names1 != null) { BufferedReader name; try { name = new BufferedReader(new InputStreamReader(names1, "UTF-8")); } catch (UnsupportedEncodingException var7) { name = new BufferedReader(new InputStreamReader(names1)); } value = name.readLine(); name.close(); if(value != null && !"".equals(value)) { if(isDiagnosticsEnabled()) { logDiagnostic("[LOOKUP] Creating an instance of LogFactory class " + value + " as specified by file \'" + "META-INF/services/org.apache.commons.logging.LogFactory" + "\' which was present in the path of the context" + " classloader."); } factory = newFactory(value, baseClassLoader, contextClassLoader); } } else if(isDiagnosticsEnabled()) { logDiagnostic("[LOOKUP] No resource file with name \'META-INF/services/org.apache.commons.logging.LogFactory\' found."); } } catch (Exception var8) { if(isDiagnosticsEnabled()) { logDiagnostic("[LOOKUP] A security exception occurred while trying to create an instance of the custom factory class: [" + var8.getMessage().trim() + "]. Trying alternative implementations..."); } } }
这段代码的意思就是说使用SPI机制,在Jar包的"META-INF/services/"目录下查找一个文件名为"org.apache.commons.logging.LogFactory"的文件,在文件中可以配置默认要使用的LogFactory具体实现类的全限定名。
2.2、自己的例子
现在有以下类层次结构
IA的内容如下:
package spi; public interface IA { void doIt(); }
AIA的内容如下:
package spi; public class AIA implements IA { public void doIt() { System.out.println("doIt In AIA"); } }
BIA的内容如下:
package spi; public class BIA implements IA { public void doIt() { System.out.println("doIt In BIA"); } }
CIA的内容如下:
package spi; public class CIA implements IA { public void doIt() { System.out.println("doIt In CIA"); } }
Main的内容如下:
package spi; import java.util.Iterator; import java.util.ServiceLoader; public class Main { public static void main(String[] args) { ServiceLoader<IA> spiLoader = ServiceLoader.load(IA.class); Iterator<IA> iaIterator = spiLoader.iterator(); while (iaIterator.hasNext()) { iaIterator.next().doIt(); } } }在META-INF/services/spi.IA文件中的内容如下:
spi.AIA spi.BIA spi.CIA
运行spi.Main,可以发现输出结果如下:
参考文献:
[1]http://singleant.iteye.com/blog/1497259
[2]http://blog.csdn.net/fenglibing/article/details/7083071
相关文章推荐
- JAVA基础针对自己薄弱环节总结02(循环)
- MyEclipse中使用复制粘贴功能卡的解决办法
- Java 容器中的泛型
- springmvc @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
- Java模式—适配器模式
- Spring获取SessionFactory
- Spring获取SessionFactory
- springmvc请求方法那些事
- Spring获取SessionFactory
- Spring获取SessionFactory
- Spring获取SessionFactory
- java正则过滤html标签属性
- Java串口助手(程序源码)
- GitHub使用for Eclipse
- Java串口助手(程序源码) 分类: Java 2015-07-30 10:13 16人阅读 评论(0) 收藏
- 举例说明Java中代码块的执行顺序
- Java类之间的数据传递3中方法。
- JAVA 并发编程-返回执行结果(Callable和Future)(九)
- java日期格式化
- JAVA多线程实现的三种方式