概述
目录
1、前文
2、Dubbo SP
第一步 首先获取对应的ExtensionLoader对象
二 代码中缓存对象
2.1 private final Holder>> cachedClasses = new Holder<>();
2.2 cachedAdaptiveClass
2.3 cachedAdaptiveInstance 缓存扩展类的instance
3 ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()过程
3.1、ExtensionLoader loader 中只有一个type属性对应
3.2、调用getAdaptiveExtension方法:
获取到ObjectFactory后返回对应的ExtensionLoader
四 第二步 首先通过getAdaptiveExtension回去自适应对象
五 ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);做了什么?
1、前文
在前面四章进行了了解dubbo中的默认服务发现、调用等逻辑后,本章对Dubbo中使用的SPI技术进行了解。
SPI全称为Service Provider Interface,Java SPI可以自行了解,本文不做叙述。
2、Dubbo SP
案例一:ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
首先查看getExtensionLoader方法做了什么:
第一步 首先获取对应的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!");
}
if (!withExtensionAnnotation(type)) {// 判断接口是否使用了@SPI注解
throw new IllegalArgumentException("Extension type (" + type +
") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
}
// 初次加载为null 需要进行new
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
if (loader == null) {
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); //根据type生成指定的ExtensionLoader
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
}
return loader;
}
首先是对其进行一些列的参数校验等,然后通过
private ExtensionLoader(Class<?> type) {
this.type = type;
// 首先生成指定的ExtensionFactory的自适应扩展类 Adaptive根据参数动态配置
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
此处type为ExtensionFactory的时候直接用null否则通过ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension() 生成对应的
ExtensionFactory
二 代码中缓存对象
@Adaptive @Spi等注解来表示对应是自适应扩展类,或是spi等
实际就是根据不同文件路径的对象进行缓存响应的class信息等
private static final String SERVICES_DIRECTORY = "META-INF/services/";
private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";
private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";
代码中进行各种缓存的存入,如封装类的缓存、实例缓存等
private Map<String, Class<?>> loadExtensionClasses() {
cacheDefaultExtensionName();
Map<String, Class<?>> extensionClasses = new HashMap<>();
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName());
loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName());
loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName());
loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"));
return extensionClasses; // 根据type.getName获取指定文件下的key,和value映射 如spring=org.apache.dubbo.config.spring.extension.SpringExtensionFactory
}
2.1 private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<>();
表示根据type获取指定配置文件下的key,value(指定类的Class对象)映射如:
spring=org.apache.dubbo.config.spring.extension.SpringExtensionFactory
2.2 cachedAdaptiveClass
adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory
根据配置文件中adaptive对应的value找到AdaptiveClass进行缓存
2.3 cachedAdaptiveInstance 缓存扩展类的instance
如2.2中AdaptiveExtensionFactory的实例
3 ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()过程
3.1、ExtensionLoader<T> loader 中只有一个type属性对应
interface org.apache.dubbo.common.extension.ExtensionFactory
3.2、调用getAdaptiveExtension方法:
根据adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory 来进行实现扩展,即
AdaptiveExtensionFactory实例对象,其中对象
private final List<ExtensionFactory> factories;
public AdaptiveExtensionFactory() {
ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
for (String name : loader.getSupportedExtensions()) { // 获取对应的key,如spi等 从对应的cachedClasses 获取到对应的实例进行具体化然后放入list
//如那么为spi则表示spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory 对应的factory
list.add(loader.getExtension(name));
}
factories = Collections.unmodifiableList(list);
}
获取到ObjectFactory后返回对应的ExtensionLoader
此时的对象为:
四 第二步 首先通过getAdaptiveExtension回去自适应对象
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses();
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
对ExtensionClasses的信息查询过程发现对应的文件目录下未指定对应的
adaptive=""的protocol相关类的信息,因此调用
createAdaptiveExtensionClass
通过debug发现
String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
package org.apache.dubbo.rpc;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
public void destroy() {
throw new UnsupportedOperationException("The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
}
public int getDefaultPort() {
throw new UnsupportedOperationException("The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");
}
public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException {
if (arg1 == null) throw new IllegalArgumentException("url == null");
org.apache.dubbo.common.URL url = arg1;
String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
return extension.refer(arg0, arg1);
}
public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
if (arg0 == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
org.apache.dubbo.common.URL url = arg0.getUrl();
String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");
org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
return extension.export(arg0);
}
}
因为接口中指定cachedDefaultName为dubbo
@SPI("dubbo")
public interface Protocol
private Class<?> createAdaptiveExtensionClass() {
String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
ClassLoader classLoader = findClassLoader();
org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
return compiler.compile(code, classLoader);
}
获取加载类,和org.apache.dubbo.common.compiler.support.AdaptiveCompiler,进行生成对应的class信息,生成一个自适应的protocol实现类。
具体实现方法会根据
org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);
return extension.export(arg0);
进行export。
五 ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);做了什么?
主要代码 getExtension(extName)其中name为默认协议"dubbo",表示根据dubbo找到对应的DubboProtocol
dubbo=org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol
public T getExtension(String name) {
if (StringUtils.isEmpty(name)) {
throw new IllegalArgumentException("Extension name == null");
}
if ("true".equals(name)) {
return getDefaultExtension();
}
final 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;
}
发现最终是DubboProtocol的一个封装,具体原因在org.apache.dubbo.common.extension.ExtensionLoader#createExtension中
会进行
injectExtension(instance);
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
通过
private Set<Class<?>> cachedWrapperClasses;
对其进行装饰最终生成对应的
ProtocolListenerWrapper
最后
以上就是魔幻香菇为你收集整理的Dubbo源码解析(五)-探索Dubbo中的SPI之Adaptive1、前文2、Dubbo SP3 ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()过程四 第二步 首先通过getAdaptiveExtension回去自适应对象五 ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExt的全部内容,希望文章能够帮你解决Dubbo源码解析(五)-探索Dubbo中的SPI之Adaptive1、前文2、Dubbo SP3 ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()过程四 第二步 首先通过getAdaptiveExtension回去自适应对象五 ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExt所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复