`
fantaxy025025
  • 浏览: 1353783 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

Java的SPI机制和例子

 
阅读更多

 

参考文档很好:http://blog.csdn.net/fenglibing/article/details/7083526

 

============================================================================

本文出自:冯立彬的博客http://blog.csdn.net/fenglibing/article/details/7083071

    一个服务(service)通常指的是已知的接口或者抽象类,服务提供方就是对这个接口或者抽象类的实现,然后按spi标准存放到资源路径META-INF/services目录下,文件的命名为该服务接口的全限定名。如有一个服务接口com.test.Service,其服务实现类为com.test.ChildService,那此时需要在META-INF/services中放置文件com.test.Service,其中的内容就为该实现类的全限定名com.test.ChildService,有多个服务实现,每一行写一个服务实现,#后面的内容为注释,并且该文件只能够是以UTF-8编码。
    这种实现方式,感觉和我们通常的开发方式差不多,都是定义一个接口,然后子类实现父类中定义的方法,为什么要搞这么一套标准以及单独搞一个配置文件?这种方式主要是针对不同的服务提供厂商,对不同场景的提供不同的解决方案制定的一套标准,举个简单的例子,如现在的JDK中有支持音乐播放,假设只支持mp3的播放,有些厂商想在这个基础之上支持mp4的播放,有的想支持mp5,而这些厂商都是第三方厂商,如果没有提供SPI这种实现标准,那就只有修改JAVA的源代码了,那这个弊端也是显而易见的,也就是不能够随着JDK的升级而升级现在的应用了,而有了SPI标准,SUN公司只需要提供一个播放接口,在实现播放的功能上通过ServiceLoad的方式加载服务,那么第三方只需要实现这个播放接口,再按SPI标准进行打包成jar,再放到classpath下面就OK了,没有一点代码的侵入性。

    以下是找到的几篇文章:

    1、http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html,这个是官方的文档,有对service的详细介绍,包括规范以及一个简单的示例,这个是学习SPI必须看的文档;

    注:http://docs.oracle.com/javase/1.4.2/docs/guide/jar/jar.html#Service%20Provider,这个是1.4中对Service Provider的介绍,加载服务是通过sun.misc.Service进行加载的,这个也有相应的示例,照做就OK;

    2、Java的SPI机制:http://www.2cto.com/kf/201012/79868.html,这个是国人写的一篇示例文章,也挺不错,里面也有一个简单的示例;

    3、Developing a Service Provider using Java API(Service Provider Interface):http://blog.csdn.net/fenglibing/article/details/7083526,这篇文章是转的alexa发表在blogspot上面的,也是一个开发SPI的示例,有兴趣的也可以看看;

    4、Add Mp3 capabilities to Java Sound with SPI:http://www.javaworld.com/javaworld/jw-11-2000/jw-1103-mp3.html,这是一个比较老的例子,基于jdk1.3的,因为在jdk1.3的时候还没有支持mp3格式,只支持AU, AIF, MIDI, and WAV等格式,也是一个值得参考的示例。

    我这边也写了一个简单得不能够再简单的示例,源码可以这里下载:http://download.csdn.net/detail/fenglibing/3939882

 

 

============================================================================

例子From:http://www.2cto.com/kf/201012/79868.html

 SPI的全名为Service Provider Interface.普通开发人员可能不熟悉,因为这个是针对厂商或者插件的。在java.util.ServiceLoader的文档里有比较详细的介绍。究其思想,其实是和"Callback"差不多。“Callback”的思想是在我们调用API的时候,我们可以自己写一段逻辑代码,传入到API里面,API内部在合适的时候会调用它,从而实现某种程度的“定制”。

    典型的是Collections.sort(List<T> list,Comparator<? super T> c)这个方法,它的第二个参数是一个实现Comparator接口的实例。我们可以根据自己的排序规则写一个类,实现此接口,传入此方法,那么这个方法就会根据我们的规则对list进行排序。

    把这个思想扩展开来,我们用SPI来重新实现上面的例子。客户把自己的排序规则写成一个类,并且打包成Jar文件,这个Jar文件里面必须有META-INF目录,其下又有services目录,其下有一个文本文件,文件名即为接口的全名:java.util.Comparator。

--META-INF
  --services
    --java.util.Comparator

文件内容只有一行:
com.company1.ComparatorProvider

这一行是你实现了Comparator接口的类的全名,它的代码如下:

package com.company1;
import java.util.Comparator;
import com.mycompany.myapp.MyItem;
public class ComparatorProvider implements Comparator<MyItem>{

    @Override
    public int compare(MyItem o1, MyItem o2) {
                //依据name排序  
        return o1.getName().compareTo(o2.getName());
    }

}

编译打包后,把它放到你的主程序的class path里。下面是你的主程序:


      //从class path中所有Jar的META-INF目录中搜索,找到合适的类并加载。
    private static ServiceLoader<Comparator> serviceLoader
    = ServiceLoader.load(Comparator.class);
    
    public static void main(String[] args)
    {
        List<MyItem> myList = new ArrayList<MyItem>();
        myList.add(new MyItem(2,"c","hhh"));
        myList.add(new MyItem(3,"k","ooo"));
        myList.add(new MyItem(4,"d","ppp"));
        myList.add(new MyItem(5,"b","ggg"));
        
        showList(myList);
        
        Collections.sort(myList,getCompartor());
        
        showList(myList);    
    }
    
    @SuppressWarnings("unchecked")
    private static Comparator<MyItem> getCompartor() {
        
        for(Comparator service : serviceLoader)
        {
           return (Comparator<MyItem>)service;
        }
               
        return null;
    }

要注意的是serviceLoader开始只是加载类,实例化要到第一次用的时候。类MyItem和方法showList并不重要,所以你不必在意。你可以按照这个规则,写另外一个排序规则的Jar,随时可以更换你的排序规则.

 

+

+

+

finished

=

=

=

 

 

 

分享到:
评论

相关推荐

    java-spi学习例子

    Java SPI(Service Provider Interface)是Java平台提供的一种服务发现机制,允许JVM在运行时动态加载服务实现。这个机制使得开发者可以扩展已存在的应用程序或库,而无需修改原代码。SPI的核心理念是将服务接口与其...

    Java SPI机制原理及代码实例

    总结,Java SPI机制为开发者提供了一种灵活的服务发现和加载方式,使得软件系统能够更好地适应变化,降低耦合度,增强系统的可扩展性和可维护性。在实际项目中,合理利用SPI可以提高软件组件的可插拔性,方便集成和...

    java spi-demo示例

    SPI机制使得开发者可以扩展程序的功能,而无需修改原代码,极大地提高了软件的可扩展性和模块化。 在Java SPI中,服务接口通常定义在`META-INF/services`目录下的一个特定配置文件中,文件名为`接口全限定名`。例如...

    Java高级玩法-SPI的基本使用

    可以使用Java 提供的SPI机制 什么是SPI?SPI和API的区别 SPI SPI的全称是Service Provider Interface,是Java提供的可用于第三方实现和扩展的机制,通过该机制,我们可以实现解耦,SPI接口方负责定义和提供默认...

    重写SPI,一个小例子

    接下来,我们需要确保在程序启动时,SPI机制能够正确地识别并加载我们的自定义提供者。这通常通过以下步骤完成: 1. 使用`java.util.ServiceLoader`类加载服务提供者。这是一个迭代器,它会遍历`META-INF/services`...

    java关于注解使用的例子

    Java注解(Annotation)是Java语言提供的一种元数据机制,它允许程序员在源代码的各个元素(如类、方法、变量等)上添加信息。这些信息可以被编译器或运行时环境用来验证代码、生成代码、配置应用程序,或者提供其他...

    SPI基础服务提者示演示

    总结一下,SPI基础服务提供者示例主要展示了如何利用Java的SPI机制来动态加载和使用服务提供者。通过`ServiceLoader`,我们可以轻松地管理和扩展应用程序的功能,而不必硬编码服务提供者的实例化过程。这种设计模式...

    SPI入门级Demo(四:服务实现者-乘法服务)

    在实际开发中,SPI机制常被用于框架和库中,如JDBC驱动、JNDI、Jackson等,它们允许用户通过添加新的实现类而无需修改原有代码,提高了系统的可扩展性和灵活性。 这个"SPI入门级Demo(四:服务实现者-乘法服务)...

    Java Service Provider实现

    总结起来,Java SPI机制是一种强大的工具,它为Java应用程序提供了高度的可扩展性和灵活性。通过正确地使用SPI,开发者可以构建出易于维护和扩展的系统,同时也能鼓励社区参与和第三方插件的开发。

    SPI入门级Demo(三:服务实现者-加法服务)

    通过这个Demo,我们学习了如何利用SPI机制来动态加载和使用服务。这种机制在很多开源框架中都有应用,比如JDBC驱动管理、JNDI服务、JAXB绑定等。SPI使得代码更加模块化,增强了可扩展性,让开发者可以轻松地添加新的...

    Java JAAS安全认证 demo

    Java Authentication and Authorization Service (JAAS) 是Java平台中用于实现用户身份验证和权限管理的核心组件。这个"Java JAAS安全认证 demo"是一个示例项目,旨在帮助开发者理解如何在Java应用中实施安全认证...

    Java9模块化demo

    6. **服务提供者接口 (SPI)**:Java 9 提供了一种改进的服务提供者注册机制,允许模块之间通过 `META-INF/services` 文件来声明服务提供者,增强了模块之间的解耦。 在 `java9test` 这个压缩包文件中,可能包含了一...

    dubbo 例子大全

    7. **SPI(Service Provider Interface)扩展机制**:Dubbo利用Java的SPI机制,允许开发者自定义实现各种扩展点,如协议、序列化方式等。 8. **Java客户端与Web客户端的区别**:Java客户端直接使用Dubbo API调用...

    classloader-playground, 一个简单的java依赖隔离容器类.zip

    这种机制保证了系统类(如java.lang.String)的一致性和安全性。 "classloader-playground"项目的核心是一个简单的Java依赖隔离容器类。在实际开发中,我们常常需要隔离不同模块之间的依赖,避免版本冲突或循环依赖...

    aether-spi-0.1-stub.jar.zip

    SPI是Java平台提供的一种机制,允许第三方开发者为特定的接口提供实现。通过在类路径下的特定目录下放置服务提供者的配置文件,应用可以在运行时动态发现并加载这些服务实现。Aether SPI可能是指Aether库中可以被...

    serviceloader:这是一个让你理解java服务加载器机制的例子

    通过理解Java服务加载器机制,开发者可以更好地利用SPI来设计可扩展的系统,同时也能更好地理解和使用已有的Java库和框架。在实际项目中,正确地使用服务加载器可以提高代码的可维护性和可扩展性,降低模块间的耦合...

    java.lang.NoClassDefFoundError: javax/persistence/EntityListener

    5. **OSGi环境问题**:在OSGi环境下,类加载机制不同于传统的Java应用。每个bundle有自己的类加载器,因此需要确保依赖的bundle已经启动并且暴露了所需的类。这可能涉及到对Spring OSGi Extender和Spring Bundle的...

    Java类加载器学习总结.pdf

    例如,JDBC驱动就是一个SPI的例子,不同的数据库供应商可以提供不同的实现,而应用可以通过SPI机制在运行时动态选择合适的驱动加载。为了实现SPI,通常会使用`java.util.ServiceLoader`类,这个类利用了线程上下文类...

    dubbo源码解析 1 pdf2.0

    在阅读Dubbo源码时,作者建议从简单的例子和模块入手,逐步深入到更复杂的机制和原理中去。在分析过程中,应不断地回顾和联系前面提到的预备知识点,这样才能在理解源码的同时,也能够学习到更广泛的知识和技能。 ...

Global site tag (gtag.js) - Google Analytics