栏目导航
最新资讯
- 马内:不再是利物浦球员很奇怪,我只是想挑战自己变得更好
- 火箭消息:联盟高管盛赞班切罗,火箭今夏计划出炉,补强中锋
- Java隐藏技-ServiceLoader
- 又有巨头官宣:全面停产燃油车!
- 三人受伤, 外援离谱攻门, 津门虎被北京国安绝杀, 于根伟沮丧退

联系我们
- 电话:
- 地址:
- 邮编:
- 传真:
Java隐藏技-ServiceLoader
2022-06-19 09:26
ServiceLoader使用介绍
JavaSE6平台提供一个新的API,可以帮助查找、加载和使用服务提供程序。其实,从Java平台的1.3版本开始,java.util.ServiceLoader类就已经悄悄存在了,但它在JavaSE6中才成为了一个公共API。
1.是什么
ServiceLoader类用于在应用程序的类路径(classPath)或运行时环境的扩展目录(java.ext.dirs)中搜索服务提供程序。它加载这些服务并给程序使用,如何新的扩展加入进来,ServiceLoader就可以找到它们,在知道接口的情况下,可以找到并使用该接口的各种实现。
2.如何使用
从官方的文档来说,它主要是用来装载一系列的serviceprovider。而且ServiceLoader可以通过serviceprovider的配置文件来装载指定的serviceprovider。看完这段话,还是比较懵,开始上示例吧。我们定义两个MessageService接口,如下:
publicinterfaceMessageService{StringgetMessage;}
有如下两种实现RawMessage如下实现:
packagecom.test.raw;importcom.test.service.MessageService;publicclassRawMessageimplementsMessageService{publicStringgetMessage{return"Rawmessage";}}
FormattedMessage如下实现:
packagecom.test.format;importcom.test.service.MessageService;publicclassFormattedMessageimplementsMessageService{publicStringgetMessage{return"Formattedmessage";}}
在原来代码的目录下面创建一个META-INF/services的目录,并创建一个com.test.service.MessageService的文件。文件名必须和我们前面定义的MessageService类的全名一样,内容如下:
com.test.raw.RawMessagecom.test.format.FormattedMessage
加载所有服务并使用:
publicclassMessageConsumer{publicstaticvoidmain(String[]args){ServiceLoaderserviceLoader=ServiceLoader.load(MessageService.class);for(MessageServiceservice:serviceLoader){System.out.println(service.getMessage);}}}
运行结果:
RawmessageFormattedmessage
像不像依赖注入的一个简单实现?我们通过配置文件可以提供一些特定的类给使用程序。当然,这里针对ServiceLoader还有一个特定的限制,就是我们提供的这些具体实现的类必须提供无参数的构造函数,否则ServiceLoader就会报错。
项目中使用的例子
try{FrameworkFactoryframeworkFactory=ServiceLoader.load(FrameworkFactory.class).iterator.next;...}catch(BundleExceptione){...}
3.一些限制
ServiceLoaderAPI很有用处,但是它有一些限制。
不能继承ServiceLoader,所以也无法修改其行为。
您可以使用自定义的ClassLoader子类来改变找到类的方式,但是无法扩展ServiceLoader本身。
当运行时有新的提供程序可用时,当前的ServiceLoader类不会告诉应用程序。同时,您无法通过添加变化监听器给加载程序,来发现是否有新的提供程序被放到特定于应用程序的扩展目录中。