Dubbo源码解读 —— Dubbo扩展点加载机制

原创
2020/03/29 22:55
阅读数 361

Dubbo源码解读 —— Dubbo扩展点加载机制

Dubbo源码解读 —— Dubbo扩展点加载机制  1、SPI介绍  2、Java SPI 实现  3、Dubbo Spi 实现  4、Dubbo 中扩展核心类源码解析  5、记录的知识点

1、SPI介绍

  • SPI : Service Provider Interface,种服务发现机制。

  • 本质是将接口实现类的全路径名配置在文件中,由服务加载器读取配置文件,加载实现类。

  • 可以在运行时,动态为接口替换实现类。

  • 可以很容易的通过 SPI 机制为我们的程序提供拓展功能。

  • SPI 机制在第三方框架中也有所应用。

2、Java SPI 实现

  1. 定义一个接口及对应的方法

    public interface IJavaSpiService {
        Object say(String param);
    }
  2. 实现接口定义的方法

    public class JavaSpiServiceImpl implements IJavaSpiService {
        @Override
        public Object say(String param) {
            System.out.println("java spi impl "+param);
            return "java spi impl";
        }
    }
    public class Java1SpiServiceImpl implements IJavaSpiService {
        @Override
        public Object say(String param) {
            System.out.println("java spi impl "+param);
            return "java spi impl";
        }
    }
  3. 数据配置文件

  4. ServiceLoader加载具体的实现类

      @Test
        public void javaSpi() {
            ServiceLoader<IJavaSpiService> spiServices = ServiceLoader.load(IJavaSpiService.class);
            spiServices.forEach(vo->{
                vo.say(vo.getClass().getCanonicalName());
            });
        }
  5. Java Spi

    • JDK标准的SPI会一次性实例化扩展点所有的实现,如果有扩展实现,则初始化很耗时,若没有,也加载,浪费资源。

    • 扩展加载失败,则获取不到扩展的名称

3、Dubbo Spi 实现

  1. Dubbo SPI 是通过键值对的方式进行配置,这样可以按需加载实现类。

  2. 可以按需加载制定的实现类。

  3. Dubbo SPI 所需的配置文件需放置在 META-INF/dubbo 路径下。

  4. Dubbo 实现了AOP 和IOC机制

  5. 实现源码:

    @SPI
    public interface IDubboSpiService {
        Object say();
    }
    public class DubboSpiServiceImpl implements IDubboSpiService {
        @Override
        public Object say() {
            System.out.println("dubbo spi impl ");
            return this.getClass().getCanonicalName();
        }
    }
        @Test
        public void dubboSpi() throws Exception {
            ExtensionLoader<IDubboSpiService> extensionLoader = ExtensionLoader.getExtensionLoader(IDubboSpiService.class);
            IDubboSpiService dubboSpiServiceImpl = extensionLoader.getExtension("dubboSpiServiceImpl");
            System.out.println(dubboSpiServiceImpl.say());
            IDubboSpiService iDubboSpiService = extensionLoader.getExtension("dubbo1SpiServiceImpl");
            System.out.println(iDubboSpiService.say());
    
        }

4、Dubbo 中扩展核心类源码解析

  • Dubbo 扩展核心类在 dubbo-common模块下,ExtensionLoader,主要方法:getExtension(获得普通扩展类)、getActivateExtension(获得自动激活扩展类)、getAdaptiveExtension(获取自适应扩展类)

  • 核心方法getExtension解读:

    • 从缓存中先获取目标对象,然后双重锁判断创建扩展实例

    • 创建扩展实例:createExtension

    • 加载扩展类,解析SPI注解

  • Dubbo IOC

    Dubbo IOC 是通过 setter 方法注入依赖。Dubbo 首先会通过反射获取到实例的所有方法,然后再遍历方法列表,检测方法名是否具有 setter 方法特征。若有,则通过 ObjectFactory 获取依赖对象,最后通过反射调用 setter 方法将依赖设置到目标对象中.方法:injectExtension

     

5、记录的知识点

  • 核心类(ExtensionLoader)如何创建?

    通过工厂类:ExtensionFactory

/**
 * ExtensionFactory
 */
@SPI
public interface ExtensionFactory {
    /**
     * Get extension.
     *
     * @param type object type.
     * @param name object name.
     * @return object instance.
     */
    <T> T getExtension(Class<T> type, String name);
}
  • Dubbo 与 Spring 打通的桥梁是?

具体实现类有:SpringExtensionFactory中有Spring上下文环境ApplicationContext

  • SPI 使用了类缓存,实例缓存,缓存使用ConcurrentMap实现


读源码不易,其读其珍惜~~

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部