仿照java的spi,dubbo实现自己的spi

1、平时遇到过的使用java的spi的例子

    1)mysql的驱动

        

2)spring-web

2、spi的设计目标

面向对象的设计里,模块之间是接口编程,模块之间不对实现类进行硬编码,如果实现类写死在代码里,想要换一种实现,就需要修改代码,为了不在代码里写死,就需要一种服务的发现机制,为某个接口寻找服务实现的机制,有点类似ioc,将装配的控制权移交到代码之外

3、spi的约定

当一个接口有多个实现类的时候,一般在META-INF/services/目录下,创建接口的同名文件(接口的包名+文件名)

文件的内容就是接口的实现类的名称(包名+文件名)

而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类java.util.ServiceLoader

4、查找接口的实现通过ServiceLoader来完成

Iterator<UserService> services = ServiceLoader.load(UserService.class).iterator();

5、dubbo为什么要实现自己的spi,而不是用jdk的spi

    1)jdk的spi会一次性实例化一个扩展点的所有实现,初始化会很耗时间,并且没有用到的实现也会加载,浪费资源

    2)增加了对扩展点ioc和aop的支持,一个扩展点可以直接setter注入其他扩展点

6、dubbo的spi的约定

dubbo spi 在JAVA自带的SPI基础上加入了扩展点的功能,即每个实现类都会对应至一个扩展点名称,其目的是 应用可基于此名称进行相应的装配。这样就解决了jdk加载全部的实现类的缺点了。

dubbo spi 目录文件

dubbo spi  文件内容:

wanglu=wanglu.dubbo.server.WlFilter

装配自定义Filter

<dubbo:provider filter="wanglu" timeout="2000" retries="2" id="abc"></dubbo:provider>

 

7、dubbo的spi的源码解析

        1)dubbo spi的目的:dubbo获取一个实现类的对象

        2)通过ExtensionLoader实现spi扩展点的加载

        途径:public T getExtension(String name)

        实现途径:

         getExtensionLoader(Class<T> type),作用就是为该Class<T>接口new一个ExtensionLoader,然后缓存起来。

         getAdaptiveExtension()  获取一个扩展装饰类的对象,这个类有一个规则,如果他没有@Adaptive注解,就动态创建一个装饰类,例如:       Protocol$Adaptive对象

       getExtension(String name)获取一个对象

    3)源码

---------------------------------------------------ExtensionLoader.getExtensionLoader(Class<T> type)
ExtensionLoader.getExtensionLoader(Container.class)
-->this.type = type;
-->objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
   -->ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
      -->this.type = type;
      -->objectFactory = null;

执行以上的代码,完成了两个属性的初始化
1、每个ExtensionLoader都包含两个值type和objectFactory
    <T> type  //构造器初始化要得到的接口名
    ExtensionFactory objectFactory 构造器,初始化时AdaptiveExtensionFactory【SpiExtensionFactory】
2、new 一个ExtensionLoader都存储在ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS
3、关于objectFactory的一些细节
    objectFactory 就是ExtensionFactory 通过ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()来实现的,但是objectFactory 为空
    objectFactory就是dubbo的IOC提供所有对象的

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章