dubbo的SPI扩展机制
作者:互联网
dubbo的SPI(Service Provider Interface)是在java的SPI基础上做了功能特性的扩展;但本质上都是做了和Spring IOC\AOP一样的事,服务(或者bean)的注册统一管理、以及实例化;此外spi提供的是一种jvm级别的服务发现机制,我们只需按照spi的要求,在jar包中进行适当的配置,jvm就会在运行时通过懒加载,帮我们找到所需要的服务并加载。如果我们一直不适用这个服务,那么他就不会被加载,一定程度上避免了资源浪费;
SPI怎么用到我们的业务服务的注册解析管理上?dubbo存在大量的扩展点,业务代码也存在大量扩展点,so.........(此处应该有总结//todo)
1、Java的SPI扩展机制
使用上就只需要注意下面几点:
- 虽然没有强制要求使用功能interface或者abstract class作为spi的注册服务,但是作为可扩展服务,尽量养成使用interface或者abstract class的习惯;
- 必须放在JAR包或项目的指定路径,即 META-INF/services 下;
- 必须以服务的全限定名命名配置文件,比如本例中,配置文件必须命名为 cn.jinlu.spi.demo.Animal,java会根据此名进行服务查找;
- 内容必须是一个实现类的全限定名,如果要注册多个实现类,按行分割。注释以#开头。;
源码解析部分:
(1)、代码入口:通过ServiceLoader的静态方法load(Class<?> service)进行服务加载
ServiceLoader的SPI服务注册发现机制
|
(2)、ServiceLoader构造:默认会使用当前线程的上下文class loader构造ServiceLoader,ServiceLoader通过实现Iterable<?>接口,使得在构造完ServiceLoader后,ServiceLoader实例并不会立刻扫描当前进程中的服务实例,而是实例化创建了一个LazyIterator懒加载迭代器,只有在实际遍历使用时再扫描所有jar包找到对应的服务。懒加载迭代器被保存在一个内部成员lookupIterator中(核心理念);
ServiceLoader
|
(3)、服务的加载和遍历
a、ServiceLoader迭代器:ServiceLoader通过实现Iterable<?>接口,将服务的实现的实例化延后到遍历是执行
- 未进行迭代时,不对jar包做扫描(即不实例化服务实现类)
- 首次迭代时,Serviceloader.providers中没有任何缓存,总是会通过LazyIterator进行加载,并将service实现的全限定名与加载的service实例作为key-value缓存到ServiceLoader.providers中
- 之后再进行迭代时,直接从ServiceLoader.providers中获取
|
b、内部私有LazyIterator懒加载迭代器,主要实现功能:
- 首次迭代时,通过ClassLoader.getResources(String)获得指定services文件的URL集合
-
如果是首次遍历懒加载器,或者对上一个URL内容解析获得的service实现类集合完成了迭代,则从configs中取下一个services文件URL进行解析,按行获得具体的service实现类集合,并进行迭代。
- 当前URL中解析得到的实现类集合进行迭代,每次返回一个service实现类。
|
java的spi最典型的应用就是jdbc的驱动加载,jdbc4.0之前JDBC的开始,总是需要通过Class.forName显式实例化驱动,否则将找不到对应DB的驱动。但是JDBC4.0开始,这个显式的初始化不再是必选项了,它存在的意义只是为了向上兼容。
为什么JDBC4.0之后不需要了呢?答案就在下面的代码中。在系统启动时,DriverManager静态初始化时会通过ServiceLoader对所有jar包中被注册为 java.sql.Driver 服务的驱动实现类进行初始化,这样就避免了上面通过Class.forName手动初始化的繁琐工作。
|
以mySql驱动为例看看驱动实例化时做了什么:
|
因此,只要某个驱动以这种方式被引用并被上下文class loader加载,那么该驱动就会通过SPI的方式被自动发现和加载。实际使用时,Driver.getDriver(url)会通过DB连接url获取到正确的驱动并建立与DB的连接。
2、Dubbo的SPI扩展机制
3、SPI在业务代码中的应用
a1290123825 发布了24 篇原创文章 · 获赞 5 · 访问量 1196 私信 关注标签:dubbo,return,service,迭代,扩展,public,SPI,ServiceLoader,加载 来源: https://blog.csdn.net/a1290123825/article/details/104126848