4、服务发现现在两个服务提供方都实现了接口,下面关键的一步就是服务发现,这一步java中的spi发现机制已经帮我们实现好了。
创建一个新项目aircondition-app,引入上面打好的两个jar包。
com.cn.hydra aircondition-hanging-type 1.0-snapshot com.cn.hydra aircondition-vertical-type 1.0-snapshot 按照上面的说法,虽然每个服务提供者对于接口都有不同的实现,但是作为调用者来说,它并不需要关心具体的实现类,我们要做的是通过接口来调用服务提供者实现的方法。
下面,就是关键的服务发现环节,我们写一个方法,根据型号去调用对应空调的开关方法。
public class airconditionapp { public static void main(string[] args) { new airconditionapp().turnon(verticaltype); } public void turnon(string type){ serviceloader测试结果:
可以看到,测试过程中,通过定义的接口iaircondition发现了两个实现类,并通过参数,调用了特定实现类的某个方法。整段代码中没有出现过具体的服务实现类,操作都是通过接口调用。
5、原理了解了spi的工作流程,我们再来看看它的实现,其实最关键的就是上面代码中出现的serviceloader这个类。
上面的示例代码中,对于serviceloader的load()方法的结果,我们用for循环进行了遍历,这一点我们看一下源码就能明白,因为serviceloader实现了iterable这一接口,而整个服务发现的核心,就在它的iterator()方法中。
注意这里面有两个关键的东西,找一下在源码中定义的地方:
注释写的非常明白,providers就是一个缓存,在迭代器中如果先从这里面进行查找,如果里面有就继续往下找,没有了的话就用这个懒加载的lookupiterator查找。
那么就简单了,接着往下看lazyiterator,看看它里面的hasnext()和next()两个方法是怎么实现的。
这个acc是一个安全管理器,在前面通过system.getsecuritymanager()判断并赋值,debug看一下这里都是null,所以直接看hasnextservice()和nextservice()方法就可以了。
在hasnextservice()方法中,会取出接口取出实现类的类名放到nextname中:
接下来,在nextservice()方法中,则会先加载这个实现类,然后实例化对象,最终放入缓存中去。
在迭代器的迭代过程中,会完成所有实现类的实例化,其实归根结底,还是基于java反射去实现的。
6、应用要说spi的实际应用,大家最常见的应该就是日志框架slf4j了,它利用spi实现了插槽式接入其他具体的日志框架。
说白了,slf4j本身就是个日志门面,并不提供具体的实现,需要绑定其他具体实现才能真正的引入日志功能。
例如我们可使用log4j2作为具体的绑定器,只需要在pom中引入slf4j-log4j12,就可以使用具体功能。
org.slf4j slf4j-api 2.0.3 org.slf4j slf4j-log4j12 2.0.3引入项目后,点开它的jar包看一下具体结构:
有没有发现一个彩蛋,先说为什么我们pom中引入的明明是slf4j-log4j12,实际上引入的是slf4j-reload4j?翻一下官网的文档:
大意就是在2015年和2022年,log4j1.x就已经宣布end of life终止了,原因也不难猜,估计是因为频繁爆出的漏洞。在那之后,slf4j-log4j在构建阶段就会自动重定向到slf4j-reload4j了,并且官方也强烈建议使用slf4j-reload4j作为替代。
再回头看一下jar包的meta-inf.services里面,通过spi注入了reload4jserviceprovider这个实现类,它实现了slf4jserviceprovider这一接口,在它的初始化方法initialize()中,会完成初始化等工作,后续可以继续获取到loggerfactory和logger等具体日志对象。
7、总结java中的spi提供了一种比较特别的服务发现和调用机制,通过接口灵活的将服务调用与服务提供者分离,用于提供给第三方实现扩展时还是很方便的。但是也有缺点,比方说一旦加载一个接口,就会把所有实现类都加载进来,可能会加载到不需要的冗余服务。不过站在整体角度上,还是给我们提供了一种非常不错的框架扩展、集成的思路。
固态继电器工作原理详细介绍
当机器人有温度后,识别物体的能力将加强
超级电容器在微型电网中的应用
什么是Docker容器
BMC Web门户不显示网卡的问题及其解决方法
Java中的SPI动态扩展(下)
兆易创新透露MCU出货量已经超4亿颗
中国联通"新起点,新征程—匠心网络万里行”活动正式拉开帷幕
呼吸灯有什么用_华为呼吸灯在哪设置
新松最新发布机器人的智能控制系统
压力传感器的类型说明
全国首座35千伏站外移动变电站投运
怎么选购vr眼镜_有哪些注意事项
荣耀V9续航测评,让不少骁龙821汗颜!
关于高功率密度电源的散热问题讲解(1)
电动车后顾之忧不用怕,IBM致力提升电池安全
戴尔灵越500014英寸轻薄本高清图赏
阻抗匹配、零欧姆电阻 ,原来它有这些作用
锐目对讲机如何配对频率
虚拟现实与增强现实,傻傻分不清楚