了解4个概念:接口,实现类,wrapper,adaptive。

扩展是接口实现类被wrap之后的对象,adaptive扩展是动态生成的类(例如Dubbo$Adaptive类)。

dubbo框架为接口指定一个同名配置文件,文件中定义了实现类(包括 wrapper)。

以dubbo-2.5.2.jar/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.protocol 文件为例,

文件内容由名值对组成(扩展名=类的全限定名)。

registry=com.alibaba.dubbo.registry.integration.RegistryProtocol
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
dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
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
redis=com.alibaba.dubbo.rpc.protocol.redis.RedisProtocol

 

provider.xml配置:

<dubbo:protocol name="dubbo" port="20880" threadpool="fixed" threads="2" iothreads="2" queues="2"/>

name="dubbo",threadpool="fixed",dubbo和fixed等都是扩展名。

每个扩展对应一个ExtensionLoader对象,ExtensionLoader对象存放在EXTENSION_LOADERS中。

private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS 
= new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();

 

以com.alibaba.dubbo.rpc.Protocol接口为例,分析整个过程:

com.alibaba.dubbo.rpc.Protocol接口对应一个ExtensionLoader实例,它的type = com.alibaba.dubbo.rpc.Protocol,静态变量EXTENSION_LOADERS中对应的键值分别是:com.alibaba.dubbo.rpc.Protocol -> ExtensionLoader<com.alibaba.dubbo.rpc.Protocol>。

public class ExtensionLoader<T> {
private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.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 static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>>
EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();
private static final ConcurrentMap<Class<?>, Object>
EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();
// 成员变量
// ==============================
private final Class<?> type;
private final ExtensionFactory objectFactory;
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>();
private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String,Class<?>>>();
private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>();
private volatile Class<?> cachedAdaptiveClass = null;
private final ConcurrentMap<String, Holder<Object>>
cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();
private String cachedDefaultName;
private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();
private volatile Throwable createAdaptiveInstanceError;
private Set<Class<?>> cachedWrapperClasses;
private Map<String, IllegalStateException> exceptions =
new ConcurrentHashMap<String, IllegalStateException>();
}

 

getExtension函数:返回指定名字的扩展(名字就是上图中的registry,filter等),极有可能返回一个wrapper。

以dubbo为例,该方法最终返回的是一个wrapper,ProtocolFilterWrapper或者ProtocolListenerWrapper。

//name = "dubbo"
public T getExtension(String name) {
if (name == null || name.length() == 0)
throw new IllegalArgumentException("Extension name == null");
if ("true".equals(name)) {
return getDefaultExtension();
}
Holder<Object> holder = cachedInstances.get(name);
if (holder == null) {
cachedInstances.putIfAbsent(name, new Holder<Object>());
holder = cachedInstances.get(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;
}

createExtension函数:

@SuppressWarnings("unchecked")
private T createExtension(String name) {
// 查找扩展对应的类
Class<?> clazz = getExtensionClasses().get(name);
if (clazz == null) {
//这个函数有点奇怪,直接返回异常。
throw findException(name);
}
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
if (instance == null) {
//使用反射创建对象
EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
injectExtension(instance);
//对原生的DubboProtocol对象进行wrap
//set中包含ProtocolFilterWrapper, ProtocolListenerWrapper
Set<Class<?>> wrapperClasses = cachedWrapperClasses;
if (wrapperClasses != null && wrapperClasses.size() > 0) {
for (Class<?> wrapperClass : wrapperClasses) {
//instance从DubboProtocol变成ProtocolFilterWrapper,然后变成ProtocolListenerWrapper
//反射翻译过来就是:
//instance = new ProtocolFilterWrapper(instance);
//instance = new ProtocolListenerWrapper(instance);
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
type + ") could not be instantiated: " + t.getMessage(), t);
}
}

 getExtensionClasses函数:

private Map<String, Class<?>> getExtensionClasses() {
//对应dubbo-2.5.2.jar/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.protoco的文件内容
//dubbo=com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
Map<String, Class<?>> classes = cachedClasses.get();
if (classes == null) {
synchronized (cachedClasses) {
classes = cachedClasses.get();
if (classes == null) {
classes = loadExtensionClasses();
cachedClasses.set(classes);
}
}
}
return classes;
}

loadExtensionClasses函数:

// 此方法已经getExtensionClasses方法同步过。
private Map<String, Class<?>> loadExtensionClasses() {
// type是com.alibaba.dubbo.rpc.Protocol
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
if(defaultAnnotation != null) {
String value = defaultAnnotation.value();
if(value != null && (value = value.trim()).length() > 0) {
String[] names = NAME_SEPARATOR.split(value);
if(names.length > 1) {
throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()
+ ": " + Arrays.toString(names));
}
if(names.length == 1) cachedDefaultName = names[0];
}
}

Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
//加载配置文件
loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
loadFile(extensionClasses, DUBBO_DIRECTORY);
loadFile(extensionClasses, SERVICES_DIRECTORY);
return extensionClasses;
}

 loadFile函数:

private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
// META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol
String fileName = dir + type.getName();
try {
Enumeration<java.net.URL> urls;
ClassLoader classLoader = findClassLoader();
if (classLoader != null) {
urls = classLoader.getResources(fileName);
} else {
urls = ClassLoader.getSystemResources(fileName);
}
if (urls != null) {
while (urls.hasMoreElements()) {
java.net.URL url = urls.nextElement();
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
try {
String line = null;
while ((line = reader.readLine()) != null) {
final int ci = line.indexOf('#');
if (ci >= 0) line = line.substring(0, ci);
line = line.trim();
if (line.length() > 0) {
try {
String name = null;
int i = line.indexOf('=');
if (i > 0) {
name = line.substring(0, i).trim();
line = line.substring(i + 1).trim();
}
if (line.length() > 0) {
Class<?> clazz = Class.forName(line, true, classLoader);
if (! type.isAssignableFrom(clazz)) {
throw new IllegalStateException("Error when load extension class(interface: " +
type + ", class line: " + clazz.getName() + "), class "
+ clazz.getName() + "is not subtype of interface.");
}
if (clazz.isAnnotationPresent(Adaptive.class)) {
if(cachedAdaptiveClass == null) {
cachedAdaptiveClass = clazz;
} else if (! cachedAdaptiveClass.equals(clazz)) {
throw new IllegalStateException("More than 1 adaptive class found: "
+ cachedAdaptiveClass.getClass().getName()
+ ", " + clazz.getClass().getName());
}
} else { //一般情况走这个分支
try {
//type = com.alibaba.dubbo.rpc.Protocol
//查找该类对应的构造函数,参数类型是type,未找到则抛出异常
//能找到的都是wrapper,例如ProtocolFilterWrapper和ProtocolListenerWrapper
clazz.getConstructor(type);
Set<Class<?>> wrappers = cachedWrapperClasses;
if (wrappers == null) {
cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
wrappers = cachedWrapperClasses;
}
wrappers.add(clazz);
} catch (NoSuchMethodException e) {
//未找到构造函数,进入该分支
clazz.getConstructor();
if (name == null || name.length() == 0) {
name = findAnnotationName(clazz);
if (name == null || name.length() == 0) {
if (clazz.getSimpleName().length() > type.getSimpleName().length()
&& clazz.getSimpleName().endsWith(type.getSimpleName())) {
name = clazz.getSimpleName().substring(0, clazz.getSimpleName().length() - type.getSimpleName().length()).toLowerCase();
} else {
throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + url);
}
}
}
String[] names = NAME_SEPARATOR.split(name);
if (names != null && names.length > 0) {
Activate activate = clazz.getAnnotation(Activate.class);
if (activate != null) {
cachedActivates.put(names[0], activate);
}
for (String n : names) {
if (! cachedNames.containsKey(clazz)) {
cachedNames.put(clazz, n);
}
Class<?> c = extensionClasses.get(n);
if (c == null) {
extensionClasses.put(n, clazz);
} else if (c != clazz) {
throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName());
}
}
}
}
}
}
} catch (Throwable t) {
IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);
exceptions.put(line, e);
}
}
} // end of while read lines
} finally {
reader.close();
}
} catch (Throwable t) {
logger.error("Exception when load extension class(interface: " +
type + ", class file: " + url + ") in " + url, t);
}
} // end of while urls
}
} catch (Throwable t) {
logger.error("Exception when load extension class(interface: " +
type + ", description file: " + fileName + ").", t);
}
}

扩展对象的创建不是一次性创建,而是在get的时候,如果没有才创建,是按需创建。

getExtension -> createExtension -> getExtensionClasses -> loadExtensionClasses

 

但是,dubbo使用扩展,并不是直接通过ExtensionLoader调用getExtension,而是调用getAdaptiveExtension方法获取最终的扩展,它是一个动态生成的xxx$Adpative类,这里是 Protocol$Adpative类。

// ReferenceConfig<T>类
private static final Protocol refprotocol =
ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

 Protocol$Adpative类代码:

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.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);
}

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);
}
}

当调用Protocol$Adpative类的refer和export方法时,才会去调用getExtension方法。

// ReferenceConfig<T>类
private static final Protocol refprotocol =
ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
private T createProxy(Map<String, String> map) {
//省略其他代码
invoker = refprotocol.refer(interfaceClass, urls.get(0));
}

 

我的问题是,为什么要这么做,感觉好绕!为了从url中获取扩展名?