通过ServiceLoader实现链式处理

转载 2014年05月16日 18:40:31

ServiceLoader与ClassLoader是Java中2个即相互区别又相互联系的加载器.JVM利用ClassLoader将类载入内存,这是一个类声明周期的第一步(一个java类的完整的生命周期会经历加载、连接、初始化、使用、和卸载五个阶段,当然也有在加载或者连接之后没有被初始化就直接被使用的情况)。详情请参阅:详解Java类的生命周期

ServiceLoader又是什么呢?ServiceLoader:一个简单的服务提供者加载设施。服务 是一个熟知的接口和类(通常为抽象类)集合。服务提供者 是服务的特定实现。提供者中的类通常实现接口,并子类化在服务本身中定义的子类。服务提供者可以以扩展的形式安装在 Java 平台的实现中,也就是将 jar 文件放入任意常用的扩展目录中。也可通过将提供者加入应用程序类路径,或者通过其他某些特定于平台的方式使其可用。……唯一强制要求的是,提供者类必须具有不带参数的构造方法,以便它们可以在加载中被实例化。

通过在资源目录META-INF/services中放置提供者配置文件 来标识服务提供者。文件名称是服务类型的完全限定二进制名称。该文件包含一个具体提供者类的完全限定二进制名称列表,每行一个。忽略各名称周围的空格、制表符和空行。注释字符为'#'('\u0023', NUMBER SIGN);忽略每行第一个注释字符后面的所有字符。文件必须使用 UTF-8 编码。 

以延迟方式查找和实例化提供者,也就是说根据需要进行。服务加载器维护到目前为止已经加载的提供者缓存。每次调用 iterator 方法返回一个迭代器,它首先按照实例化顺序生成缓存的所有元素,然后以延迟方式查找和实例化所有剩余的提供者,依次将每个提供者添加到缓存。可以通过 reload 方法清除缓存。

……

以上来源于Java API里的说明,也许说的很专业,让我们有点晕头转向,我们可以简单的认为:ServiceLoader也像ClassLoader一样,能装载类文件,但是使用时有区别,具体区别如下:(1) ServiceLoader装载的是一系列有某种共同特征的实现类,而ClassLoader是个万能加载器;(2)ServiceLoader装载时需要特殊的配置,使用时也与ClassLoader有所区别;(3)ServiceLoader还实现了Iterator接口。

下面是关于ServiceLoader的简单的例子,仅供参考

(1)基础服务:IService

1 package com.service;
2 public interface IService {
3     String sayHello();
4     String getScheme();
5 }


(2)具体服务实现1:HDFSService

01 package com.impl;
02 import com.service.IService;
03 public class HDFSService implements IService {
04     @Override
05     public String sayHello() {
06         return "Hello HDFSService";
07     }
08     @Override
09     public String getScheme() {
10         return "hdfs";
11     }
12 }


(3)具体服务实现2:LocalService

01 package com.impl;
02 import com.service.IService;
03 public class LocalService  implements IService {
04     @Override
05     public String sayHello() {
06         return "Hello LocalService";
07     }
08     @Override
09     public String getScheme() {
10         return "local";
11     }
12 }
(4)配置:META-INF/services/com.service.IService


1 com.impl.HDFSService
2 com.impl.LocalService
(5)测试类
01 package com.test;
02 import java.util.ServiceLoader;
03 import com.service.IService;
04 public class Test {
05     public static void main(String[] args) {
06         ServiceLoader<IService> serviceLoader  = ServiceLoader.load(IService.class);
07         for (IService service : serviceLoader) {
08             System.out.println(service.getScheme()+"="+service.sayHello());
09         }
10     }
11 }


结果:

hdfs=Hello HDFSService
local=Hello LocalService

可以看到ServiceLoader可以根据IService把定义的两个实现类找出来,返回一个ServiceLoader的实现,而ServiceLoader实现了Iterable接口,所以可以通过ServiceLoader来遍历所有在配置文件中定义的类的实例。


ServiceLoader的应用

(1)Hadoop FileSystem

Hadoop FileSystem就是通过这个机制来根据不同文件的scheme来返回不同的FileSystem。

01 private static void loadFileSystems() { 
02   synchronized (FileSystem.class) { 
03     if (!FILE_SYSTEMS_LOADED) { 
04       ServiceLoader<FileSystem> serviceLoader = ServiceLoader.load(FileSystem.class); 
05       for (FileSystem fs : serviceLoader) { 
06         SERVICE_FILE_SYSTEMS.put(fs.getScheme(), fs.getClass()); 
07       
08       FILE_SYSTEMS_LOADED = true
09     
10   
11 }
对应的配置文件:

1 org.apache.hadoop.fs.LocalFileSystem 
2 org.apache.hadoop.fs.viewfs.ViewFileSystem 
3 org.apache.hadoop.fs.s3.S3FileSystem 
4 org.apache.hadoop.fs.s3native.NativeS3FileSystem 
5 org.apache.hadoop.fs.kfs.KosmosFileSystem 
6 org.apache.hadoop.fs.ftp.FTPFileSystem 
7 org.apache.hadoop.fs.HarFileSystem
通过之前的测试类输出对应的scheme和class如下: 
file=class org.apache.hadoop.fs.LocalFileSystem   
viewfs=class org.apache.hadoop.fs.viewfs.ViewFileSystem   
s3=class org.apache.hadoop.fs.s3.S3FileSystem   
s3n=class org.apache.hadoop.fs.s3native.NativeS3FileSystem   
kfs=class org.apache.hadoop.fs.kfs.KosmosFileSystem   
ftp=class org.apache.hadoop.fs.ftp.FTPFileSystem   
har=class org.apache.hadoop.fs.HarFileSystem   
hdfs=class org.apache.hadoop.hdfs.DistributedFileSystem   
hftp=class org.apache.hadoop.hdfs.HftpFileSystem   
hsftp=class org.apache.hadoop.hdfs.HsftpFileSystem   
webhdfs=class org.apache.hadoop.hdfs.web.WebHdfsFileSystem  

可以看到FileSystem会把所有的FileSystem的实现都以scheme和class来cache,之后就从这个cache中取相应的值。因此,以后可以通过ServiceLoader来实现一些类似的功能,而不用依赖像Spring这样的第三方框架。

(2)责任链模式

责任链模式的定义:使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有一个对象处理它为止。

责任连模式可以使用ServiceLoader实现具体服务对象的迭代加载并处理,为了确保此模式的灵活性,建议判断逻辑通过配置文件或数据库的方式,具体实现方式见 参考链接(2) 消灭成堆的……


参考资料:

(1)java.util.ServiceLoader使用

(2)消灭成堆的分支语句之类责任链模式 

(3)转一篇很不错的介绍NetBeans的文章

附:测试用例文件的文件结构


转自:http://my.oschina.net/hanzhankang/blog/109794

ServiceLoader跟DriverManager使用总结

http://www.myexception.cn/program/1355384.html
  • hintcnuie
  • hintcnuie
  • 2014年07月18日 09:36
  • 4221

promise链式小技巧

Promise
  • naihejiang
  • naihejiang
  • 2016年12月15日 09:55
  • 978

ServiceLoader的使用

发现ServiceLoader是个类似spring的东西,可以指定接口和实现,通过ServiceLoader去载入。  下面是我的一个例子:  Java代码   package com.te...
  • z69183787
  • z69183787
  • 2016年05月04日 06:34
  • 940

请求的链式处理——责任链模式

什么是责任链模式职责链可以是一条直线、一个环或者一个树形结构,最常见的职责链是直线型,即沿着一条单向的链来传递请求。链上的每一个对象都是请求处理者,职责链模式可以将请求的处理者组织成一条链,并让请求沿...
  • Todo_
  • Todo_
  • 2016年02月22日 10:57
  • 1553

请求的链式处理—职责链模式

转自:http://blog.csdn.net/lovelion/article/details/74208911 采购单的分级审批Sunny软件公司承接了某企业SCM(Supply Chain Ma...
  • cds86333774
  • cds86333774
  • 2016年03月24日 18:03
  • 205

C 算法精介----哈希表->链式哈希表->分析与实现

经典的字符串哈希函数   /*hashpjw.c*/ unsigned int hashpjw(const void *key) { const char *ptr; ...
  • liutianshx2012
  • liutianshx2012
  • 2015年02月03日 10:26
  • 1259

hadoop中使用java.util.ServiceLoader

在前一篇文章Hadoop源码解析之YARN客户端作业提交流程中,介绍了创建客户端代理阶段用到java.util.ServiceLoader加载YarnClientProtocolProvider和Lo...
  • liushahe2012
  • liushahe2012
  • 2017年01月24日 22:46
  • 328

java.util.ServiceLoader源码分析

java.util.ServiceLoader源码分析 回顾: ServiceLoader类的使用(具体参考博客http://blog.csdn.net/liangyihuai/article/d...
  • liangyihuai
  • liangyihuai
  • 2016年02月22日 14:39
  • 1079

链式结构实现线性表的基本操作

#include #include typedef int Elementype; typedef struct Node { Elementype data; struct No...
  • kavu1
  • kavu1
  • 2015年09月07日 20:54
  • 824

js的链式调用-如何实现类似jquery的链式调用

这里我是参考别人的一篇博客写的。如果有冲突请及时联系,我会立马修改的。 不知道我的理解对不对。请大家指教。 首先介绍一下链式调用的特点和优点把:他的优点是代码简洁易读,减少了多次重复使用同一个变量...
  • sufubo
  • sufubo
  • 2015年10月07日 20:35
  • 4445
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:通过ServiceLoader实现链式处理
举报原因:
原因补充:

(最多只允许输入30个字)