1. 几个不错的关于ServiceLoader的文章,大家可以先参考一下

1) http://www.myexception.cn/program/1355384.html 这篇的后面的问题分析不错

2.实例代码

直接上代码吧
1) 接口
  1. package com.ctrip.lzyan.test.element.serviceloader.sample1;
  2.  
  3. public interface Command {
  4.  
  5. public void execute();
  6.  
  7. }

2) 实现类

  1. package com.ctrip.lzyan.test.element.serviceloader.sample1;
  2.  
  3. public class StartCommand implements Command {
  4.  
  5. public void execute() {
  6. System.out.println("start....");
  7. }
  8.  
  9. }
  1. package com.ctrip.lzyan.test.element.serviceloader.sample1;
  2.  
  3. public class ShutdownCommand implements Command {
  4.  
  5. @Override
  6. public void execute() {
  7. System.out.println("shutdown....");
  8. }
  9.  
  10. }

3) 配置文件

由于是使用maven构建的项目,所以就在resources下面新建目录META-INF/services,在该目录下新建文件com.ctrip.lzyan.test.element.serviceloader.sample1.Command, 即完整的接口名
文件内容如下:
  1. com.ctrip.lzyan.test.element.serviceloader.sample1.StartCommand
  2. com.ctrip.lzyan.test.element.serviceloader.sample1.ShutdownCommand

4) 测试类

  1. package com.ctrip.lzyan.test.element.serviceloader.sample1;
  2.  
  3. import java.util.ServiceLoader;
  4.  
  5. public class CommandTester {
  6.  
  7. public static void main(String[] args) {
  8. ServiceLoader<Command> serviceLoader = ServiceLoader.load(Command.class);
  9. for(Command command:serviceLoader){
  10. command.execute();
  11. }
  12. }
  13.  
  14. }

5) 编译执行

  1. mvn clean install -Dmaven.test.skip=true
  2. mvn exec:java -Dexec.mainClass=com.ctrip.lzyan.test.element.serviceloader.sample1.CommandTester

3.activemq中的使用实例

第一次接触到ServiceLoader就是在activemq的启动过程中,所以学习了一下
activemq broker启动时,调用的是org.apache.activemq.console.command.ShellCommand 类,ShellCommand.main调用runTask,runTask会调用getCommands方法,下面看一下getCommands的代 码:
  1. ArrayList<Command> getCommands() {
  2. ServiceLoader<Command> loader = ServiceLoader.load(Command.class);
  3. Iterator<Command> iterator = loader.iterator();
  4. ArrayList<Command> rc = new ArrayList<Command>();
  5. boolean done = false;
  6. while (!done) {
  7. try {
  8. if( iterator.hasNext() ) {
  9. rc.add(iterator.next());
  10. } else {
  11. done = true;
  12. }
  13. } catch (ServiceConfigurationError e) {
  14. // it's ok, some commands may not load if their dependencies
  15. // are not available.
  16. }
  17. }
  18. return rc;
  19. }

ServiceLoader会读取META-INF/services/org.apache.activemq.console.command.Command 配置的类并在迭代时将其实例化。

回头看一下runTask方法:
  1. protected void runTask(List<String> tokens) throws Exception {
  2.  
  3. // Process task token
  4. if (tokens.size() > 0) {
  5. Command command=null;
  6. String taskToken = (String)tokens.remove(0);
  7.  
  8. for( Command c: getCommands() ) {
  9. if( taskToken.equals(c.getName()) ) {
  10. command = c;
  11. break;
  12. }
  13. }
  14. if( command == null ) {
  15. if (taskToken.equals("help")) {
  16. printHelp();
  17. } else {
  18. printHelp();
  19. }
  20. }
  21.  
  22. if( command!=null ) {
  23. command.setCommandContext(context);
  24. command.execute(tokens);
  25. }
  26. } else {
  27. printHelp();
  28. }
  29.  
  30. }

该方法根据类名选择Command,并执行。

问题:

1.配置文件为什么要放在META-INF/services下面?
ServiceLoader.PREFIX定义如下:

  1. private static final String PREFIX = "META-INF/services/";
  1. 但是如果ServiceLoaderload时提供Classloader,则可以从其他的目录读取。
  1. ServiceLoader.LazyIterator.nextService中实例化,即load的结果迭代时才会被实例化。
  2.  

转自:

http://blog.csdn.net/unei66/article/details/47051017

Java ServiceLoader(SPI)学习的更多相关文章

  1. Java之SPI机制

    之前开阿里的HSF框架,里面用到了Java的SPI机制,今天闲暇的时候去了解了一下,通过写博客来记录一下 SPI的全名为Service Provider Interface,我对于该机制的理解是为接口 ...

  2. java 的SPI机制

    今天看到spring mvc 使用Java Validation Api(JSR-303)进行校验,需要加载一个 其具体实现(比如Hibernate Validator), 本来没有什么问题,但是突然 ...

  3. Java的SPI机制与简单的示例

    一.SPI机制 这里先说下SPI的一个概念,SPI英文为Service Provider Interface单从字面可以理解为Service提供者接口,正如从SPI的名字去理解SPI就是Service ...

  4. java的spi 的简单应用

    1.什么是java的spi SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制. 目前有不少框架用它来做服务的扩展发现, 简单来说,它就是一 ...

  5. JAVA的SPI简单应用

    最近在研究dubbo时,发现了JAVA的SPI特性.SPI的全名为Service Provider Interface,是JDK内置的一种服务发现机制. 具体实现: 1.定义一个接口 public i ...

  6. Java的spi介绍和简单应用

    1.什么是java的spi SPI 全称为 (Service Provider Interface) ,是JDK内置的一种服务提供发现机制. 目前有不少框架用它来做服务的扩展发现, 简单来说,它就是一 ...

  7. 深入理解 Java 中 SPI 机制

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/vpy5DJ-hhn0iOyp747oL5A作者:姜柱 SPI(Service Provider ...

  8. JAVA中SPI机制

    之前研究dubbo的时候就很好奇,里面各种扩展机制,期间也看过很多关于SPI的机制,今日有缘再度看到有文章总结,故记录一下, 首先了解一下 JAVA中SPI简单的用法 可参考这篇文章,https:// ...

  9. java的spi(Service Provider Interface)机制及源码(java8)

    1.什么是java的spi spi 全称为 service provider interface 即 服务提供接口,用来作为服务的扩展发现.在运行时动态添加接口的实现,是对接口的实现类的创建管理. 2 ...

随机推荐

  1. 编写自定义Yeoman生成器简述

    1. 安装生成器Yeoman提供了generator-generator方便快速编写自己的生成器. 安装: npm install -g generator-generator运行: yo gener ...

  2. android开发(49) Android 下拉刷新的实现。使用 SwipeRefreshLayout 代替 pull-to-refesh

    概述 谷歌官方推出了SwipeRefreshLayout 来实现下拉刷新的效果.对比以前我们常用的 pull-to-refesh ,这个方案显得更加的简单方便. 关联项目引用(管理依赖) 在你的 应用 ...

  3. Git 推送操作

    Jerry 修改了他的最后一次提交的修改操作,他已经准备好将更改.推操作的数据永久存储的 Git 仓库.推操作成功后,其他开发人员可以看到Jerry 的变化. 他执行的git日志命令来查看提交的细节. ...

  4. Java知多少(58)线程Runnable接口和Thread类详解

    大多数情况,通过实例化一个Thread对象来创建一个线程.Java定义了两种方式: 实现Runnable 接口: 可以继承Thread类. 下面的两小节依次介绍了每一种方式. 实现Runnable接口 ...

  5. CentOS 添加 Oracle YUM 源

    最新文章:Virson's Blog 文章来自:Oracle 官方 YUM 源 Introduction The Oracle public yum server offers a free and ...

  6. Git -- 使用GitHub

    我们一直用GitHub作为免费的远程仓库,如果是个人的开源项目,放到GitHub上是完全没有问题的.其实GitHub还是一个开源协作社区,通过GitHub,既可以让别人参与你的开源项目,也可以参与别人 ...

  7. Failed to read schema document 'http://code.alibabatech.com/schema/dubbo/dubbo.xsd'问题解决方法

    Failed to read schema document 'http://code.alibabatech.com/schema/dubbo/dubbo.xsd'问题解决方法 关于dubbo服务的 ...

  8. [Hinton] Neural Networks for Machine Learning - Bayesian

    Link: Neural Networks for Machine Learning - 多伦多大学 Link: Hinton的CSC321课程笔记 Lecture 09 Lecture 10 提高泛 ...

  9. [IR] What is XML

    Concept: http://www.w3school.com.cn/xml/xml_cdata.asp Semistructured: 和普通纯文本相比,半结构化数据具有一定的结构性.OEM(Ob ...

  10. java.util.Queue(队列)的简单使用

    import java.util.LinkedList; import java.util.Queue; import org.junit.Before; import org.junit.Test; ...