文章来源:https://dwz.cn/b0UieE77作者:Java知音
java里面提供了一种内置的服务提供和发现机制,可以通过配置让一个程序在运行的时候动态加载该类的具体实现。这样子我们可以在调用某个相应接口的时候,同时达到调用某些具体类的实现功能。
具体的代码案例如下所示:
首先定义一个接口和两个接口的实现类
接口
/** * @author idea * @date 2019/5/16 */public interface PersonAction { void say();}
接口实现类
![62de04be4dd6aa5ae5419fe159c51d8d.png](https://i-blog.csdnimg.cn/blog_migrate/96bb18c91e92e7e46dc3ad5ebd564472.jpeg)
然后我们需要在META-INF/services的文件夹底下配置一份文件:
(ps:这里的配置文件命名方式为类所在包名+类名)
![1a5338ea2564be7394266beafaa61031.png](https://i-blog.csdnimg.cn/blog_migrate/dd55617617cb83ea02adc431c20c38c3.jpeg)
这份文件里面加入以下的配置信息:
(ps:文件里面输入的内容是表示类所在的地址全称,因为java的spi进行类加载的时候需要知道类所在的路径)
com.sise.dubbo.spi.SpiMainTestcom.sise.dubbo.spi.SpiSubTest
接着是编写测试类代码
![dbf4b3d95502f50e3bc87fde4fd4b85d.png](https://i-blog.csdnimg.cn/blog_migrate/04b183bd54bdbc05500affe6453dbf64.jpeg)
当我们执行代码之后,会发现控制台输出了相应的内容:
this is java spithis is a SpiMainTestthis is a SpiSubTest
其实jdk自带的spi功能的实现原理分为了以下几步
1.首先通过java.util.ServiceLoader来加载META-INF/services/文件夹底下的类信息
2.在运行期间需要引用相关类的时候,对加载到内存的类进行搜索和分析,进行实例化调用。
为什么是META-INF/services该文件夹呢?
在ServiceLoader类里面,我们可以通过阅读源码看到它在加载配置的时候会指定默认的加载位置META-INF/services文件夹。
ServiceLoader会将该文件底下的配置类信息全部加载存储到内存中,然后在接口进行实例化的时候提供相应的实现类进行对象的实例化功能。这一点和ioc的思想有点类似,通过一个可插拔式的方式来对类的实例化进行控制。
![8acae38c15ff5b2c950d5b10bc9863b3.png](https://i-blog.csdnimg.cn/blog_migrate/899a6b08926f9d9eafe0848134598319.jpeg)