Dubbo---SPI机制源码解析
2021-08-29 16:02:37 0 举报
AI智能生成
SPI流程和核心类解析
作者其他创作
大纲/内容
SPI扩展机制
SPI
定义
SPI (Service Provider Interface)。JDK设计的一种为某接口寻找服务实现机制。
应用:
1. jdbc定义接口,加载外部数据库驱动实现
2. slfj 加载不同日志实现
应用:
1. jdbc定义接口,加载外部数据库驱动实现
2. slfj 加载不同日志实现
dubbo SPI 和 JDK SPI区别
实现方式
JDK SPI 通过ServiceLoader加载jar中的META-INF/services/路径下的SPI实现配置文件
Dubbo SPI 通过自定义的ExtensionLoader加载jar中META-INF/dubbo/接口全限定名的SPI实现配置问文件,
配置内容为 配置名称 = 实现类的全限定类名
配置内容为 配置名称 = 实现类的全限定类名
加载方式
JDK SPI 一次性实例化扩展点所有的实现。
有可能加载应用没有用上的扩展实现类,造成资源的浪费。
扩展点加载失败时报不支持的类型,不知道具体加载失败的扩展点。
有可能加载应用没有用上的扩展实现类,造成资源的浪费。
扩展点加载失败时报不支持的类型,不知道具体加载失败的扩展点。
Dubbo SPI 可以指定 扩展点的配置名称加载。
提供了增强功能:
①扩展点自动装配(IOC)
②AOP的支持
③扩展点的自适应
提供了增强功能:
①扩展点自动装配(IOC)
②AOP的支持
③扩展点的自适应
API与SPI区别 代码位置不同
API通常是单独的jar包,只有接口的定义,没有接口的实现类
SPI应用的实现jar包,配置依赖不同的实现类
面向的角色不同
框架通常有两类客户,一个是使用者,一个是扩展者。
API是给使用者用的;
SPI是给扩展者用的;
框架通常有两类客户,一个是使用者,一个是扩展者。
API是给使用者用的;
SPI是给扩展者用的;
API通常是单独的jar包,只有接口的定义,没有接口的实现类
SPI应用的实现jar包,配置依赖不同的实现类
扩展点自适应
扩展自适应实例其实就是一个Extension的代理,它实现了扩展点接口.在调用扩展点接口方法时,根据实际参数来决定要使用哪个扩展.
使用自适应的原因
Dubbo中配置有两种,一种是固定的系统级别的配置,dubbo启动之后不会再改变;另一种是运行时配置,每一次RPC调用时这些配置都不同.以调用时的参数配置覆写系统级别配置,在调用时做出正确的决定
很多时候,我们的类都是一个单例的,比如Spring的bean,在Spring bean都实例化时,如果它依赖某个扩展点,但是bean实例化时,是不知道究竟该使用哪个具体的扩展实现的.这个时候需要一个代理模式了,它实现了扩展点接口,方法内部可以根据运行时参数,动态的选择合适的扩展实现.这个代理就是自适应实例.自适应扩展实例在Dubbo中的使用非常广泛,Dubbo中,每一个扩展都会有一个自适应类,如果我们没有提供,Dubbo会使用字节码工具为我们自动生成一个.
IOC功能
加载扩展点时,自动注入依赖的扩展点.加载扩展点时,扩展点实现类的成员如果为其他扩展点类型,ExtensionLoader会自动注入依赖的扩展点.ExtensionLoader通过扫描扩展点实现类的所有setter方法来判定其成员.即ExtensionLoader会执行扩展点的拼接操作.
AOP功能
自动包装扩展点的Wrapper类.ExtensionLoader在加载扩展点时,如果加载到的扩展点有拷贝函数,则判定为扩展点Wrapper类.
Wrapper类同样实现了扩展点接口,但是Wrapper不是扩展点的真正实现.它的用途主要是用于从ExtensionLoader返回扩展点时,包装在真正的扩展点实现外.即从ExtensionLoader中返回的实际上是Wrapper类的实例,Wrapper持有了实际的扩展点实现类.
扩展点的Wrapper类可以有多个(多个切面),也可以根据需要新增.通过Wrapper类可以把所有扩展点公共逻辑移至Wrapper中.新加的Wrapper在所有的扩展点上添加了逻辑,有些类似AOP,即Wrapper代理了扩展点.
wrapper规范
该类要实现 SPI 接口
该类中要有 SPI 接口的引用
该类中必须含有一个含参的构造方法且参数只能有一个类型为SPI接口
在接口实现方法中要调用 SPI 接口引用对象的相应方法
该类名称以 Wrapper 结尾
该类中要有 SPI 接口的引用
该类中必须含有一个含参的构造方法且参数只能有一个类型为SPI接口
在接口实现方法中要调用 SPI 接口引用对象的相应方法
该类名称以 Wrapper 结尾
Dubbo SPI核心类
@SPI
标注一个接口是一个扩展点,可以被Dubbo的ExtensionLoader加载
@Adaptive
作用在类上,Dubbo源码中实现好的自适应扩展实现类,
AdaptiveExtensionFactory和AdaptiveCompiler使用该注解
AdaptiveExtensionFactory和AdaptiveCompiler使用该注解
作用在方法上,表示是一个自适应方法,Dubbo在扩展点生成自适应实例时,
会为该方法生成对应的代码,方法内部根据方法的参数,来决定使用哪个扩展
会为该方法生成对应的代码,方法内部根据方法的参数,来决定使用哪个扩展
@Active
扩展点自动激活,应用于集合类扩展点如Filter
@Activate("xxx"),当配置了xxx参数,并且参数值为有效值时激活
@Activate(group="provider",value="xxx"),只对提供方激活
@Activate("xxx"),当配置了xxx参数,并且参数值为有效值时激活
@Activate(group="provider",value="xxx"),只对提供方激活
ExtensionLoader
核心属性
缓存扩展类型的加载类(ExtensionLoader)实例
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>(64);
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>(64);
缓存加载过的扩展实现类实例
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>(64);
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>(64);
定义ExtensionLoader实例加载的扩展点(接口)类型
private final Class<?> type;
private final Class<?> type;
缓存扩展实例配置名和扩展实现类类名
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();
定义扩展点实现IOC功能的工厂,Dubbo实现有的SpiExtensionFactory和SpringExtensionFactory,并且支持自适应适配
private final ExtensionFactory objectFactory;
private final ExtensionFactory objectFactory;
构造器
私有化构造器,初始化时指定加载扩展的类型
private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory =(type == ExtensionFactory.class ? null :
ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
private ExtensionLoader(Class<?> type) {
this.type = type;
objectFactory =(type == ExtensionFactory.class ? null :
ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
加载指定name的扩展点实例
//获取扩展点的ExtensionLoader实例
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type)
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type)
//获取指定配置名称的扩展实现类
public T getExtension(String name)
public T getExtension(String name)
//没有从缓存中获取到,则创建一个实例
private T createExtension(String name)
private T createExtension(String name)
//查询扩展点实现类的类型
private Map<Strring,Class<?> getExtensionClasses()
private Map<Strring,Class<?> getExtensionClasses()
//如果没有从缓存中查询到对象的扩展点类型对象,则开始从配置目录加载
private Map<String, Class<?>> loadExtensionClasses()
private Map<String, Class<?>> loadExtensionClasses()
//扫描文件路径下的SPI扩展配置文件
private void loadDirectory()
private void loadDirectory()
//读取配置文件实例化扩展点配置的CLass实例
private void loadResource()
private void loadResource()
IOC自动装配功能实现
//createExtension方法中初始化实例后调用InjectExtension方法通过setter方式注入依赖的属性
private T injectExtension(T instance)
private T injectExtension(T instance)
//通过objectFactory进行依赖查找,进行反射调用注入
Object object = objectFactory.getExtension(pt, property);
Object object = objectFactory.getExtension(pt, property);
AOP功能warpper实现
private Set<Class<?>> cachedWrapperClasses;//缓存wrapper Class
try {
clazz.getConstructor(type);
Set<Class<?>> wrappers = cachedWrapperClasses;
if (wrappers == null) {
cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
wrappers = cachedWrapperClasses;
}
wrappers.add(clazz);
} catch (NoSuchMethodException e) {}
try {
clazz.getConstructor(type);
Set<Class<?>> wrappers = cachedWrapperClasses;
if (wrappers == null) {
cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
wrappers = cachedWrapperClasses;
}
wrappers.add(clazz);
} catch (NoSuchMethodException e) {}
自适应扩展实例
//获取扩展点的自适应实例
public T getAdaptiveExtension()
public T getAdaptiveExtension()
Dubbo实现的Adaptive扩展点有ExtensionFactory 和AdaptiveCompiler,
其他的自适应实例都是通过拼接动态代码编译后生成的
其他的自适应实例都是通过拼接动态代码编译后生成的
//调用这个方法表明Dubbo的源码中没有实现当前扩展点的自适应实例,需要动态创建
private T createAdaptiveExtension()
private T createAdaptiveExtension()
//根据当前扩展点接口动态生成需要自适应的方法实现,包含拼接代码和编译过程
private Class<?> createAdaptiveExtensionClass()
private Class<?> createAdaptiveExtensionClass()
ExtensionFactory
AdaptiveExtensionFactory
//初始化时在构造器中加载Dubbo配置所支持的ExtensionFactory扩展实例
private final List<ExtensionFactory> factories;
private final List<ExtensionFactory> factories;
//构造器中,初始化Dubbo支持的extensionFactory实例
public AdaptiveExtensionFactory(){
ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
List<ExtensionFactory> list = new ArrayList<>();
//加载项目配置支持的ExtensionFactory类
for (String extension : loader.getSupportedExtensions()) {
ExtensionFactory factory = loader.getExtension(extension);
list.add(factory);
}
factories = Collections.unmodifiableList(list);
}
public AdaptiveExtensionFactory(){
ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
List<ExtensionFactory> list = new ArrayList<>();
//加载项目配置支持的ExtensionFactory类
for (String extension : loader.getSupportedExtensions()) {
ExtensionFactory factory = loader.getExtension(extension);
list.add(factory);
}
factories = Collections.unmodifiableList(list);
}
//实现ExtensionFactory接口的获取指定名称的实例,循环factories从具体的ObjectFactory实现中查找
public <T> T getExtension(Class<T> clazz, String name)
public <T> T getExtension(Class<T> clazz, String name)
SPIExtensionFactory
实现ExtensionLoader接口,使用Dubbo自定的ExtensionLoader加载指定name的扩展实现实例,
这里返回的实例是一个Adaptive的实例,为了实现扩展点的自适应功能
这里返回的实例是一个Adaptive的实例,为了实现扩展点的自适应功能
SpringExtensionFactory
从Spring容器中加载指定name和Class对象的实例
Holder<T>
把一个对象包装一下,使用volatile修饰 当前对象,保证关键对象的可见性
0 条评论
下一页