dubbo ExtensionLoader源码分析

本文详细分析了Dubbo的ExtensionLoader源码,包括ExtensionLoader的属性、ExtensionFactory的功能、SPI机制、自适应扩展和激活扩展。核心功能在于对象工厂、对象创建和查询。SPI机制加载接口实现类,AdaptiveExtensionFactory实现了自适应选择。此外,还讨论了Dubbo的IOC和装饰器模式。
摘要由CSDN通过智能技术生成

ExtensionLoader概述

  • 你无需先知道 扩展点,SPI,自适应 概念
  • ExtensionLoader中最核心功能是创建对象,几乎所有的dubbo框架接口实现类对象都在该类中创建
  • 对象在增删改查,为提升效率、有缓存参与;单个接口多个实现类、根据参数加载具体实现类,或加载对应接口多个实现类

ExtensionLoader属性

  • ExtensionLoader核心功能就是对以下属性的增删改查,弄清楚每个属性作用,则对ExtensionLoader就门清了

  • EXTENSION_LOADERS,EXTENSION_INSTANCES 作为常量存储,放到任何常量类中都可以

  • 每个接口Class会创建对应的ExtensionLoader对象,并存储到 EXTENSION_LOADERS 中

  • 每个接口的多个实现类Class创建的对应实例,存储到EXTENSION_INSTANCES;so 在java进程中通常对应接口实现类对象是单例的

  • 其他属性需要在对应应用场景中解释

  • 从属性命名中可将【extension:扩展】理解为对象实例

  • ExtensionFactory【对象工厂】 起到什么作用?

public class ExtensionLoader<T> {

    // 常量存储 {class-ExtensionLoader} pair对
    private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>(64);

    // 常量存储 {实现类class对象 ~ 实现类实例} pair对
    private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>(64);

    // 接口class
    private final Class<?> type;

    // 对象工厂,不同接口对应 ExtensionLoader 的对象工厂属性是相同的
    private final ExtensionFactory objectFactory;

    /****以下属性是对象实例不同维度的缓存 需要在具体使用场景中理解*****/ 
    private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();

    private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();

    private final Map<String, Object> cachedActivates = new ConcurrentHashMap<>();
    private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();
    private final Holder<Object> cachedAdaptiveInstance = new Holder<>();
    private volatile Class<?> cachedAdaptiveClass = null;
    private String cachedDefaultName;
    private volatile Throwable createAdaptiveInstanceError;

    private Set<Class<?>> cachedWrapperClasses;

    private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<>();

    // 接口对应实现类名称存储路径
    private static volatile LoadingStrategy[] strategies = loadLoadingStrategies();
    ...
}

ExtensionFactory 与 ExtensionLoader的关系

  • 每个接口Class会创建对应的ExtensionLoader对象

  • 每个ExtensionLoader<?>对象持有的ExtensionFactory属性是AdaptiveExtensionFactory;除去ExtensionLoader<ExtensionFactory>

  • ExtensionLoader<ExtensionFactory> 持有的ExtensionFactory属性是null

  • AdaptiveExtensionFactory类对象在整个应用运行中只有一个,为啥不采用静态属性?个人思考是因为 ExtensionLoader<ExtensionFactory> 对象 不需要ExtensionFactory属性

public class ExtensionLoader<T> {
   private ExtensionLoader(Class<?> type) {
        this.type = type;
        // 创建objectFactory的【Adaptive:自适应】实例 或 不创建
        // 先不用管自适应是什么含义
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
    }

    private static <T> boolean withExtensionAnnotation(Class<T> type) {
        return type.isAnnotationPresent(SPI.class);
    }

    // 通过接口Class get 对应ExtensionLoader<?> 对象
    // ExtensionLoader 中最常用的方法;通常第一步先获取到接口class对应的ExtensionLoader对象
    @SuppressWarnings("unchecked")
    public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
        if (type == null) {
            throw new IllegalArgumentException("Extension type == null");
        }
        if (!type.isInterface()) {
            throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
        }
        // 接口必须有@SPI注解, dubbo框架的规定
        // 如需要通过dubbo SPI 方式加载实现类需要遵守该规定
        // SPI 方式加载,下文有解释
        if (!withExtensionAnnotation(type)) {
            throw new IllegalArgumentException("Extension type (" + type +
                    ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
        }
        // 从存储常量map中获取 
        ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        if (loader == null) {
            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
            loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        }
        return loader;
    }
}

ExtensionFactory 功能

  • 对象工厂全局只有一个ExtensionFactory的 AdaptiveExtensionFactory实例

  • 通过SPI方式加载SpiExtensionFactory,SpringExtensionFactory实例,并存储到factories 列表中

  • SpiExtensionFactory 中getExtension 会从对应ExtensionLoader<?>中获取adaptive 对象实例

  • SpringExtensionFactory 中getExtension 会从ApplicationContext中获取bean 对象实例

  • AdaptiveExtensionFactory 中getExtension 会 for循环factories 调用getExtension 获取bean对象

  • 项目中有可能会存在多个 bean工厂 如:dubbo框架 的SPI bean工厂,Spring框架 bean 工厂, Guice框架 bean工厂,自定义 bean工厂

  • AdaptiveExtensionFactory 构造器中会初始化所有bean工厂到factories列表中

  • 通过AdaptiveExtensionFactory 工厂可以获取到任何bean工厂中对应的bean对象

  • 此时的【adaptive:自适应】可理解为加载对应接口所有实现类,getExtension方法会遍历调用对应实现类的getExtension方法

  • 什么是SPI加载方式,自适应还有哪些解释?

// 该类有@Adaptive
// 对应ExtensionLoader<ExtensionFactory> 中 
// cachedAdaptiveInstance,cachedAdaptiveClass,createAdaptiveInstanceError 
// 属性都与AdaptiveExtensionFactory相关
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {

    // 所有ExtensionFactory实现类实例对象【排查AdaptiveExtensionFactory】
    // ExtensionLoader<ExtensionFactory>实例中cachedAdaptiveInstance属性是 AdaptiveExtensionFactory对象实例
    private final List<ExtensionFac
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值