本篇内容介绍了“什么是ServiceLoader解耦服务”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
SPI,全称Service Provider Interfaces
,服务提供接口。是Java提供的一套供第三方实现或扩展使用的技术体系。主要通过解耦服务具体实现以及服务使用,使得程序的可扩展性大大增强,甚至可插拔。
基于服务的注册与发现机制,服务提供者向系统注册服务,服务使用者通过查找发现服务,可以达到服务的提供与使用的分离,甚至完成对服务的管理。
JDK中,基于SPI的思想,提供了默认具体的实现,ServiceLoader
。利用JDK自带的ServiceLoader
,可以轻松实现面向服务的注册与发现
,完成服务提供与使用的解耦
。
完成分离后的服务,使得服务提供方的修改或替换,不会给服务使用方带来代码上的修改,基于面向接口的服务约定,提供方和使用方各自直接面向接口编程,而不用关注对方的具体实现。同时,服务使用方使用到服务时,也才会真正意义上去发现服务
,以完成服务的初始化
,形成了服务的动态加载
。
ServiceLoader代码片段
说明
外部使用时,往往通过load(Class<S> service, ClassLoader loader)
或load(Class<S> service)
调用,最后都是在reload
方法中创建了LazyIterator
对象,LazyIterator
是ServiceLoader
的内部类,实现了Iterator
接口,其作用是一个懒加载的迭代器,在hasNextService
方法中,完成了对位于META-INF/services/
目录下的配置文件的解析,并在nextService
方法中,完成了对具体实现类的实例化。
JDK的ServiceLoader通过返回一个Iterator对象能够做到对服务实例的懒加载 只有当调用iterator.next()方法时才会实例化下一个服务实例,只有需要使用的时候才进行实例化,具体实现读者可以去阅读源码进行研究,这也是其设计的亮点之一。
META-INF/services/
,是ServiceLoader
中约定的接口与实现类的关系配置目录,文件名是接口全限定类名,内容是接口对应的具体实现类,如果有多个实现类,分别将不同的实现类都分别作为每一行去配置。解析过程中,通过LinkedHashMap<String,S>
数据结构的providers
,将已经发现了的接口实现类进行了缓存,并对外提供的iterator()
方法,方便外部遍历。
总体上,ServiceLoader
的一般实现与使用过程包含了服务接口约定
、服务实现
、服务注册
、服务发现与使用
这四个步骤。
r2dbc-mariadb实际也是基于r2dbc-spi的方式实现服务解耦
服务接口约定: r2dbc-spi
服务实现:r2dbc-mariadb对r2dbc-spi的实现
服务注册:r2dbc-mariadb包中META-INF.service文件
服务发现:在r2dbc-spi中创建连接工厂的方法
public static ConnectionFactory find(ConnectionFactoryOptions connectionFactoryOptions) { Assert.requireNonNull(connectionFactoryOptions, "connectionFactoryOptions must not be null"); for (ConnectionFactoryProvider provider : loadProviders()) { if (provider.supports(connectionFactoryOptions)) { return provider.create(connectionFactoryOptions); } } return null; } private static ServiceLoader<ConnectionFactoryProvider> loadProviders() { return AccessController.doPrivileged((PrivilegedAction<ServiceLoader<ConnectionFactoryProvider>>) () -> ServiceLoader.load(ConnectionFactoryProvider.class, ConnectionFactoryProvider.class.getClassLoader())); }
之所以ServiceLoader能够发现ZenithConnectionFactoryProvider,是因为在r2dbc-zenith的META-INF.service文件中添加响应的类路径声明(注册自己)以供ServerLoader扫描。
其他应用,如:jdbc-driver
“什么是ServiceLoader解耦服务”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。