1.Dubbo的可扩展机制SPI源码解析
(1)概念:
是对Java原生SPI的增强,支持扩展点自动包装、自动装配和自适应扩展。核心思想是通过配置文件定义接口实现类,运行时动态加载
(2)核心类解析
**ExtensionLoader:**作为SPI核心入口类,负责扩展点的加载、缓存和管理。
- 核心参数:
type参数用于指定扩展点的接口或抽象类。它定义了需要加载的扩展实现的类型。通过type,ExtensionLoader能够识别并加载所有符合该接口的实现类。例如,在Dubbo中指定一个协议接口,ExtensionLoader会扫描类路径下META-INF/services/等目录下的对应文件,加载所有注册的实现。
objectFactory 是用于创建扩展点实例的工厂对象。当ExtensionLoader需要实例化扩展实现时,会通过objectFactory完成对象的创建。默认情况下可能使用反射实例化,但通过自定义objectFactory可以实现依赖注入、代理增强等高级功能。例如,在Spring集成场景中,objectFactory可能委托Spring容器管理扩展实例的生命周期。
- 关键方法
-
getExtension(获取指定名称的扩展): 第一步先检查扩展名合法性,若非法则抛出IllegalArgumentException 若是否禁用@Disbable标记,禁用则返回空值,第二步通过ConcurrentHashMap<string,Holder<Object>>类型的缓存
EXTENSION_INSTANCES中获取实例,若缓存命中且实例初始化则返回缓存实列,若没有命中则调用createExtension方法。将新创建的实例存入缓存EXTENSION_INSTANCES,返回实例给调用方。javapublic T getExtension(String name) { // 检查扩展名 if (StringUtils.isEmpty(name)) { throw new IllegalArgumentException("Extension name == null"); } // 检查禁用状态 if ("true".equals(name)) { return getDefaultExtension(); } // 从缓存获取Holder Holder<Object> holder = getOrCreateHolder(name); Object instance = holder.get(); // 双重检查锁定 if (instance == null) { synchronized (holder) { instance = holder.get(); if (instance == null) { instance = createExtension(name); holder.set(instance); } } } return (T) instance; } -
getAdaptiveExtension(获取自适应扩展):
-
getActivateExtension(获取激活的扩展)。
@SPI注解:标记接口为可扩展接口,value属性指定默认实现名。例如:
java
@SPI("dubbo")
public interface Protocol {}
@Adaptive注解:标记自适应扩展点,可动态选择具体实现。若注解在类上,则该类为固定自适应类;若注解在方法上,Dubbo会动态生成自适应代码。
(3)实现流程
-
加载扩展配置
扫描
META-INF/dubbo/、META-INF/dubbo/internal/和META-INF/services/目录下的文件,格式为key=implementationClass。 -
实例化扩展类
通过反射创建实例,并检查是否包含
@Adaptive注解。若存在则缓存为自适应扩展。 -
依赖注入
通过
injectExtension方法实现IoC,自动注入其他扩展点。使用ExtensionFactory查找依赖对象。 -
包装类处理
识别实现了扩展接口的包装类(如
ProtocolFilterWrapper),通过装饰器模式增强功能。
(4)自适应扩展生成
2.Dubbo整合Spring源码解析