java.util.ServiceLoader demo

首先引用API中的说明文档:

 

一个简单的服务提供者加载设施。

 

服务 是一个熟知的接口和类(通常为抽象类)集合。服务提供者 是服务的特定实现。提供者中的类通常实现接口,并子类化在服务本身中定义的子类。服务提供者可以以扩展的形式安装在 Java 平台的实现中,也就是将 jar 文件放入任意常用的扩展目录中。也可通过将提供者加入应用程序类路径,或者通过其他某些特定于平台的方式使其可用。

 

为了加载,服务由单个类型表示,也就是单个接口或抽象类。(可以使用具体类,但建议不要这样做。)一个给定服务的提供者包含一个或多个具体类,这些类扩展了此服务类型 ,具有特定于提供者的数据和代码。提供者类 通常不是整个提供者本身而是一个代理,它包含足够的信息来决定提供者是否能满足特定请求,还包含可以根据需要创建实际提供者的代码。提供者类的详细信息高度特定于服务;任何单个类或接口都不能统一它们,因此这里没有定义任何这种类型。此设施唯一强制要求的是,提供者类必须具有不带参数的构造方法,以便它们可以在加载中被实例化。

 

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

 

....还有其他的一些就不拷贝过来了。

 

 

从说明中可以看出,这个机制允许服务的声明与实现的分离,具体使用哪个实现可以在运行时才决定,使用哪个实现取决于是否部署了该实现。下面是个简单的demo。

 

1、首先定义一个表示服务的接口:

package learn.serviceLoader.service;

import java.util.ServiceLoader;

public abstract class SimpleService {
	public abstract void doService();

	private static boolean isInit = false;
	private static SimpleService service = null;

	public static final SimpleService getService() {
		if (!isInit) {
			ServiceLoader<SimpleService> serviceLoader = ServiceLoader
					.load(SimpleService.class);
			for (SimpleService s : serviceLoader) {
				service = s;
				break;
			}

			isInit = true;
		}

		return service;
	}
}

 

此接口定义了服务的能力,同时提供了工厂方法来获取服务的实例。这个工厂方法就是通过此机制来查找服务的实现的。

 

 

2、实现服务提供者。

package learn.serviceLoader.serviceimpl;

import learn.serviceLoader.service.SimpleService;

public class StandarService extends SimpleService {

	@Override
	public void doService() {
		System.out
				.println("i am standar service, i implement SimpleService, so you get here .");
	}
}

 就是实现服务接口的方法。

 

 

3、在服务提供者jar中下配置:

    a、建立一个META-INF文件夹,在META-INF文件夹下建立一个services文件夹;

    b、在services文件夹下建立服务配置文件,如:learn.serviceloader.service.SimpleService

        里面的内容就是提供者的全限定类名:learn.serviceLoader.serviceimpl.StandarService    # comment

 

 

4、服务的使用者:

package learn.serviceLoader.test;

import learn.serviceLoader.service.SimpleService;

public class TestServiceLoader {

	public static void main(String[] args) {
		SimpleService service = SimpleService.getService();
		service.doService();
		
		SimpleService service2 = SimpleService.getService();
		service2.doService();
	}
}

 服务的使用者通过服务接口的工厂方法来获取服务,使用者并不知道、也不需要知道使用的是哪个服务提供者。

 

 

对于复杂的使用,应该将服务的声明放在单独的api.jar包,不同的实现放在不同的jar,部署时只需要部署api.jar和特定的提供者jar包。此机制还支持  “reload ()   清除此加载器的服务者缓存,以重载所有服务者。”,应该可以预留方法,实现动态切换服务提供者。

 

 

这是个简单又强大的机制,可以方便地实现服务声明与实现的分离。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值