配置JDK SPI失败,竟如此简单问题都解决不了?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1395个文字,预计阅读时间需要6分钟。
今天去幼儿园接小侄女,路上聊起天。小侄女说:小叔,今天我吃的东西被老师发现了+我:老师说了什么+小侄女:她说拿出去,跟小朋友一起分享+我:那你拿出来了没+小侄女:我拿出来了,跟小朋友一起吃了。
开心一刻今天去幼儿园接小侄女,路上聊起了天
小侄女:小叔,今天我吃东西被老师发现了
我:老师说了什么
小侄女:她说拿出来,跟小朋友一起分享
我:那你拿出来了吗
小侄女一脸可怜的看向我,说道:没有,我没有那么多鼻屎
SPI 概念SPI 全称Service Provider Interface,直译过来就是:服务提供接口,是不是有点抽象?
简单点理解,Java SPI 就是提供这样的一个机制:为某个接口寻找服务实现的机制
还是抽象?我们往下看它的具体实现就好理解了
实现三板斧1、接口与实现
Animal 接口
Dog 实现
Cat 实现
2、配置文件
配置文件有点讲究,需要按这套规则来
2.1 在src/main/resources/下建立目录:/META-INF/services,位置和名字都必须严格按这个来,一字都不能差
2.2 在/META-INF/services目录下创建一个以接口全限定类名为名的文件:com.qsl.service.Animal,没有额外的后缀
2.3 将接口实现类的全限定类名写入到 2.2 创建的文件中,一个实现占一行
3、ServiceLoader 加载
通过ServiceLoader进行加载,代码很简单,如下所示
正常情况下会输出如下内容
示例工程结构如下
至此,对SPI的感觉是不是没那么抽象了
简单理解,Java SPI是基于接口的编程+策略模式+配置文件实现的动态加载机制
使用场景不太好概括,一千个人眼中有一千个哈姆雷特
但是我们可以通过一些案例来形成自己的概括
1、DriverManager
不知道大家还记得JDBC的写法吗
我们去跟下DriverManager的源码
我们再看下MySQL驱动的包结构
2、SLF4J
具体源码我就不带大家去跟了,有兴趣的可以去看看:从源码来理解slf4j的绑定,以及logback对配置文件的加载 中的问题1
3、Spring SPI
Spring有自己的SPI实现机制,和JDK SPI略有不同
Spring是在src/main/resources/META-INF目录下创建spring.factories,里面以键值对的方式存放多个实现,类似如下
4、Dubbo SPI
Dubbo又有自己的一套实现,配置文件需要放到META-INF/dubbo目录下
具体细节可查看其官方文档:Dubbo SPI
问题重现此刻,大家是不是觉得JDK SPI很简单?
但正是这么简单的东西,楼主都碰到了问题,如下图所示
当时人就懵了!!!
问题排查一度怀疑是不是JDK SPI还有额外的配置
因为是工作中的项目出了这个问题,所以我自建了一个demo来验证实现三板斧
结果demo的执行是没问题的,这也就说明JDK SPI的实现就只有那三板斧,那问题出在哪了?
本着快速解决问题的目的,我换了一种实现方式,采用Spring SPI
结果依然是有问题,同样是读不到spring.factories中的配置
正在一筹莫展之际,直觉告诉我是不是maven构建出了问题,所以我对项目进行了package,然后去看了下打好的包的目录结构
META-INF目录下的com.qsl.service.Animal文件了?
肯定是pom.xml配置不对
我是万万没想到pom.xml会进行如上的配置(后面问了老同事,没特别的原因,就是简单的认为只会有 xml 和 yml 配置文件)
此刻,相信大家都知道怎么改了吧(去掉<includes>标签,或者在<includes>中加上)
然而楼主没用采用上述两种方案的任一一个,也没有改pom.xml,就问你气不气?
总结1、JDK SPI的使用,就那三板斧,如果出了问题,不用想,肯定不是JDK SPI的问题
2、关于SPI的使用场景,楼主仍然不做概括(太菜,概括不好),大家自行去概括
3、关于pom.xml
楼主之前写过一篇:Maven pom.xml中的元素modules、parent、properties以及import
但就是没讲<build>,下次补上,你们记得提醒我哦!
本文共计1395个文字,预计阅读时间需要6分钟。
今天去幼儿园接小侄女,路上聊起天。小侄女说:小叔,今天我吃的东西被老师发现了+我:老师说了什么+小侄女:她说拿出去,跟小朋友一起分享+我:那你拿出来了没+小侄女:我拿出来了,跟小朋友一起吃了。
开心一刻今天去幼儿园接小侄女,路上聊起了天
小侄女:小叔,今天我吃东西被老师发现了
我:老师说了什么
小侄女:她说拿出来,跟小朋友一起分享
我:那你拿出来了吗
小侄女一脸可怜的看向我,说道:没有,我没有那么多鼻屎
SPI 概念SPI 全称Service Provider Interface,直译过来就是:服务提供接口,是不是有点抽象?
简单点理解,Java SPI 就是提供这样的一个机制:为某个接口寻找服务实现的机制
还是抽象?我们往下看它的具体实现就好理解了
实现三板斧1、接口与实现
Animal 接口
Dog 实现
Cat 实现
2、配置文件
配置文件有点讲究,需要按这套规则来
2.1 在src/main/resources/下建立目录:/META-INF/services,位置和名字都必须严格按这个来,一字都不能差
2.2 在/META-INF/services目录下创建一个以接口全限定类名为名的文件:com.qsl.service.Animal,没有额外的后缀
2.3 将接口实现类的全限定类名写入到 2.2 创建的文件中,一个实现占一行
3、ServiceLoader 加载
通过ServiceLoader进行加载,代码很简单,如下所示
正常情况下会输出如下内容
示例工程结构如下
至此,对SPI的感觉是不是没那么抽象了
简单理解,Java SPI是基于接口的编程+策略模式+配置文件实现的动态加载机制
使用场景不太好概括,一千个人眼中有一千个哈姆雷特
但是我们可以通过一些案例来形成自己的概括
1、DriverManager
不知道大家还记得JDBC的写法吗
我们去跟下DriverManager的源码
我们再看下MySQL驱动的包结构
2、SLF4J
具体源码我就不带大家去跟了,有兴趣的可以去看看:从源码来理解slf4j的绑定,以及logback对配置文件的加载 中的问题1
3、Spring SPI
Spring有自己的SPI实现机制,和JDK SPI略有不同
Spring是在src/main/resources/META-INF目录下创建spring.factories,里面以键值对的方式存放多个实现,类似如下
4、Dubbo SPI
Dubbo又有自己的一套实现,配置文件需要放到META-INF/dubbo目录下
具体细节可查看其官方文档:Dubbo SPI
问题重现此刻,大家是不是觉得JDK SPI很简单?
但正是这么简单的东西,楼主都碰到了问题,如下图所示
当时人就懵了!!!
问题排查一度怀疑是不是JDK SPI还有额外的配置
因为是工作中的项目出了这个问题,所以我自建了一个demo来验证实现三板斧
结果demo的执行是没问题的,这也就说明JDK SPI的实现就只有那三板斧,那问题出在哪了?
本着快速解决问题的目的,我换了一种实现方式,采用Spring SPI
结果依然是有问题,同样是读不到spring.factories中的配置
正在一筹莫展之际,直觉告诉我是不是maven构建出了问题,所以我对项目进行了package,然后去看了下打好的包的目录结构
META-INF目录下的com.qsl.service.Animal文件了?
肯定是pom.xml配置不对
我是万万没想到pom.xml会进行如上的配置(后面问了老同事,没特别的原因,就是简单的认为只会有 xml 和 yml 配置文件)
此刻,相信大家都知道怎么改了吧(去掉<includes>标签,或者在<includes>中加上)
然而楼主没用采用上述两种方案的任一一个,也没有改pom.xml,就问你气不气?
总结1、JDK SPI的使用,就那三板斧,如果出了问题,不用想,肯定不是JDK SPI的问题
2、关于SPI的使用场景,楼主仍然不做概括(太菜,概括不好),大家自行去概括
3、关于pom.xml
楼主之前写过一篇:Maven pom.xml中的元素modules、parent、properties以及import
但就是没讲<build>,下次补上,你们记得提醒我哦!

