總結:?Protocolrefprotocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
首先會生成自適應ExtensionFactory ,根據URL可適配的工廠包含兩個spi 和 spring;
然后才會真正的去生成Protocol的自適應對象(代碼生成,并運行時編譯),其可適配的對象就比較多了,例如dubbo,http等等
AAA 1 默認首次執行
ExtensionFactory 自適應實現
private ExtensionLoader(Class type) {
? ? this.type = type;
? ? objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory
讀取:指定包下的擴展配置
ExtensionLoader.class.getClassLoader()
urls = classLoader.getResources(fileName);
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory
文件內容:
spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
1 解析url
spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
name=spring
line=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
Class clazz = Class.forName(line, true, classLoader);
interface
type=com.alibaba.dubbo.common.extension.ExtensionFactory
放入extensionClasses? cache: clazz = com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
2 解析url
adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
name=adaptive? 包含SPI 和 Spring 兩個擴展工廠
line=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
緩存adaptive--class不會放到extensionClasses 因為這個累就是 自適應擴展類
cachedAdaptiveClass= com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
3 解析url
spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
name=spi
line=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
clazz=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
extensionClasses.put(n, clazz);
AAA 2 自適應擴展類 使用該類:
com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
@Adaptive? 自適應擴展類 代碼實現
public class AdaptiveExtensionFactory implements ExtensionFactory {
? ? private final List factories;
? ? public AdaptiveExtensionFactory() {
ExtensionLoader loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
? ? ? ? List list = new ArrayList();
? ? ? ? for (String name : loader.getSupportedExtensions()) {
? ? ? ? ? ? list.add(loader.getExtension(name));
? ? ? ? }
? ? ? ? factories = Collections.unmodifiableList(list);
? ? }
? ? public T getExtension(Class type, String name) {
? ? ? ? for (ExtensionFactory factory : factories) {
? ? ? ? ? ? T extension = factory.getExtension(type, name);
? ? ? ? ? ? if (extension != null) {
? ? ? ? ? ? ? ? return extension;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return null;
? ? }
}
自適應擴展工廠:包含spi,spring兩個擴展工廠
BBB 其次才會繼續加載protocol:
對應的文件內容
registry=com.alibaba.dubbo.registry.integration.RegistryProtocol
dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper
listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper
mock=com.alibaba.dubbo.rpc.support.MockProtocol
injvm=com.alibaba.dubbo.rpc.protocol.injvm.InjvmProtocol
rmi=com.alibaba.dubbo.rpc.protocol.rmi.RmiProtocol
hessian=com.alibaba.dubbo.rpc.protocol.hessian.HessianProtocol
com.alibaba.dubbo.rpc.protocol.http.HttpProtocol
com.alibaba.dubbo.rpc.protocol.webservice.WebServiceProtocol
thrift=com.alibaba.dubbo.rpc.protocol.thrift.ThriftProtocol
memcached=memcom.alibaba.dubbo.rpc.protocol.memcached.MemcachedProtocol
java.lang.ClassNotFoundException: memcom.alibaba.dubbo.rpc.protocol.memcached.MemcachedProtocol
redis=com.alibaba.dubbo.rpc.protocol.redis.RedisProtocol
其中對應的filter listener
filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper
listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper
會單獨緩存到Set> cachedWrapperClasses中
異常--->放置到exceptions中
// 完全沒有Adaptive方法,則不需要生成Adaptive類
//有類型為URL的參數 或者參數中有 getUrl()方法 -- 則可以創建 adaptive class 作者拼寫錯誤為 adative
//生成具體的擴展類實例
com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
動態編譯的java代碼文件
package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adpative implements com.alibaba.dubbo.rpc.Protocol {
public void destroy() {throw new UnsupportedOperationException("method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
}
public int getDefaultPort() {throw new UnsupportedOperationException("method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
}
public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.Invoker {
if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");com.alibaba.dubbo.common.URL url = arg0.getUrl();
String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
return extension.export(arg0);
}
public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws java.lang.Class {
if (arg1 == null) throw new IllegalArgumentException("url == null");
com.alibaba.dubbo.common.URL url = arg1;
String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
return extension.refer(arg0, arg1);
}
}