Java之ServiceLoader
转载请注明源出处:http://www.cnblogs.com/lighten/p/6946683.html
1.简介
JDK1.6之后,java.util包下多了一个类ServiceLoader,其实现了Iterable接口(可以直接进行for-each loop)。这个类的主要作用是提供了一种服务发现机制,并没有什么深奥的内容。实现过程也十分简单,下面通过一个例子来详细讲解一下如何使用和其实现过程。本文基于jdk1.8。
2.例子
ServiceLoader的使用是要在根目录有一个文件夹META-INF/services/,其主要是对这个目录进行扫描,文件名是你需要提供服务的类(接口)全称(即包名.类名)。类中的内容,一行就是改接口的一个具体的实现类。包结构如下:

服务的定义和实现具体如下:
public interface TestService {
public String sayHello();
}
public class TestServiceImpl1 implements TestService {
@Override
public String sayHello() {
return "hello, test1";
}
}
public class TestServiceImpl2 implements TestService {
@Override
public String sayHello() {
return "hello, test2";
}
}
配置文件就是实现类的类全称:
com.java.util.test.TestServiceImpl1
com.java.util.test.TestServiceImpl2
配置完成后就是最主要的使用方法了:
public class ServiceLoaderTest {
public static void main(String[] args) {
ServiceLoader<TestService> loader = ServiceLoader.load(TestService.class);
for(TestService service : loader) {
System.out.println(service.sayHello());
}
}
}
运行一下结果如下:

使用起来也很简单,就是通过静态方法load进行加载,然后通过for-each循环遍历,使用这个实现类。
3.源码解读
ServiceLoader解析服务并不是加载就立刻解析的,其采取的是懒加载的方式,也就是第一次使用这个loader对象的时候才进行解析。
1.先看属性:

这里就定义了读取的文件名,service是需要加载的类,loader是类加载器,默认使用当前加载器,providers是服务提供者,lookupIterator就是懒加载的具体实现了。
2.再看loader方法:

loader方法就是初始化了一些属性,清空了providers。
3.关键的iterator()方法,这个是Iterable接口需要实现的一个方法:

其遍历,是先通过providers来遍历,因为解析完成后这里应该是有值的,如果没值,就通过lookupIterator去遍历,这里也就看出并不是loader就开始读取然后解析,而是在遍历的时候,没找到解析的值,再通过设置的懒加载遍历器,去解析遍历。
4.核心的LazyIterator,其实现了Iterator接口,next和hasNext实际上调用的是其另两个方法,nextService与hasNextService

上面代码很简单,就是读取META-INF/services文件夹下,所加载类的类全称名的文件,通过parse方法解析。

nextService方法也很简单,就是通过实现类的类全称,通过Class.forName进行加载。然后判断该实现类是不是加载类的子类,service.isAssignableFrom,再通过service.cast()方法进行转换成所加载的类。
5.parse解析文件步骤:

用utf-8的格式读取,然后调用parseLine方法,一行行读取到name这个迭代器中。

读取一行,截取#注释前面的内容,通过trim方法去掉两端空格。若还有值,则判断是否有空格或制表符,有即不符合规则,查看是不是Java标识的开头。都满足规则,如果providers中没有且未解析过相同的,就放入迭代器中。
至此,这个解析过程就明了了,就是读取指定文件夹的指定文件,文件中存的类全称,通过Class.forName,拿到字节码,再通过class.newInstance方法获得实例,将其cast成所要加载的类。
Java之ServiceLoader的更多相关文章
- java.util.ServiceLoader的用法
在很多开源组件里经常会看到java.util.ServiceLoader的使用,这里给大家介绍下怎么通过ServiceLoader找到一个接口的所有实现类. 我们新建一个接口Hello public ...
- java.util.ServiceLoader使用
近期在项目中需要实现能在配置文件中定义多个统一接口类型的类,可以在程序中获取到所有配置的类,刚开始打算配置到properties中,然后去程序读取,感觉这种方式不太灵活,于是,研究研究java中有没有 ...
- 【Java】ServiceLoader源码分析
ServiceLoader主要的功能是用来完成对SPI的provider的加载. 先看下它的成员: public final class ServiceLoader<S> implemen ...
- Java ServiceLoader(SPI)学习
1. 几个不错的关于ServiceLoader的文章,大家可以先参考一下 1) http://www.myexception.cn/program/1355384.html 这篇的后面的问题分析不错 ...
- 【java编程】ServiceLoader使用看这一篇就够了
转载:https://www.jianshu.com/p/7601ba434ff4 想必大家多多少少听过spi,具体的解释我就不多说了.但是它具体是怎么实现的呢?它的原理是什么呢?下面我就围绕这两个问 ...
- Java SPI机制:ServiceLoader实现原理及应用剖析
一.背景 SPI,全称Service Provider Interfaces,服务提供接口.是Java提供的一套供第三方实现或扩展使用的技术体系.主要通过解耦服务具体实现以及服务使用,使得程序的可扩展 ...
- Java DNS查询内部实现
源码分析 在Java中,DNS相关的操作都是通过通过InetAddress提供的API实现的.比如查询域名对应的IP地址: String dottedQuadIpAddress = InetAddre ...
- java中的SPI机制
1 SPI机制简介 SPI的全名为Service Provider Interface.大多数开发人员可能不熟悉,因为这个是针对厂商或者插件的.在java.util.ServiceLoader的文档里 ...
- JAVA流程控制
JAVA流程控制 example1: --输出九九乘法表 public class chengfabiao { public static void main (String[] args){ ...
随机推荐
- linux 定时器 定时执行php
输入命令: crontab -e 添加定时命令 每隔一分钟执行一次php //复制一下命令即可. */1 * * * * /usr/bin/curl -o /home/logs/temp.lo ...
- 高性能高可用的分布式唯一ID服务——mooon-uniq-id
目录 目录 1 1. 前言 1 2. 名词 1 3. 功能 1 4. 唯一性原理 2 5. 系统结构 2 5.1. mooon-uniq-agent 2 5.2. mooon-uniq-master ...
- CentOS和Ubuntu哪个好?
CentOS(Community ENTerprise Operating System)是Linux发行版之一,它是来自于Red Hat Enterprise Linux依照开放源代码规定释出的源代 ...
- spring之jdbcTemplate
spring的另一个功能模块data access对于数据库的支持 spring data access第一个helloword案例: 使用java程序实现访问配置 1.导包 2.测试案例 @Test ...
- java基础-day19
第08天 异常 今日内容介绍 u 异常体系&异常处理 u Throwable常用方法&自定义异常 u 递归 第1章 异常产生&异常处理 1.1 异常概述 什 ...
- The Seven Percent Solution
Problem Description Uniform Resource Identifiers (or URIs) are strings like http://icpc.baylor.edu/i ...
- Hdu1054 Strategic Game(最小覆盖点集)
Strategic Game Problem Description Bob enjoys playing computer games, especially strategic games, bu ...
- ZUFE2481 神奇的字符串 2017-05-12 16:41 39人阅读 评论(0) 收藏
2481: 神奇的字符串 时间限制: 3 Sec 内存限制: 256 MB 提交: 8 解决: 3 [提交][状态][讨论版] 题目描述 输入 输出 样例输入 abcb 1000 1100 350 ...
- hdu 5084 前缀和预处理
http://acm.hdu.edu.cn/showproblem.php?pid=5084 给出矩阵M,求M*M矩阵的r行c列的数,每个查询跟前一个查询的结果有关. 观察该矩阵得知,令ans = M ...
- centos7 搭建WEB服务器
centos7 搭建WEB服务器 2017年09月17日 09:44:50 逝然1994 阅读数:18321 标签: centosapacheweb服务器 更多 个人分类: centos服务器简单配置 ...