从以下代码,可以看到dubbo默认的服务是failover
@SPI("failover")
public interface Cluster {
String DEFAULT = "failover";
@Adaptive
<T> Invoker<T> join(Directory<T> directory, boolean buildFilterChain) throws RpcException;
static Cluster getCluster(ScopeModel scopeModel, String name) {
return getCluster(scopeModel, name, true);
}
static Cluster getCluster(ScopeModel scopeModel, String name, boolean wrap) {
if (StringUtils.isEmpty(name)) {
name = "failover";
}
return (Cluster)ScopeModelUtil.getApplicationModel(scopeModel).getExtensionLoader(Cluster.class).getExtension(name, wrap);
}
}
但是debug,可以看到cluster 调到了MockClusterWrapper,这个是怎么来的呢?
核心代码都在ExtensionLoader 类里面,
先看load
private void loadClass(ClassLoader classLoader, Map<String, Class<?>> extensionClasses,
java.net.URL resourceURL, Class<?> clazz, String name,
boolean overridden) {
if (!type.isAssignableFrom(clazz)) {
throw new IllegalStateException(
"Error occurred when loading extension class (interface: " + type + ", class line: " + clazz.getName() + "), class " + clazz.getName() + " is not subtype of interface.");
}
if (name.equals("failover")){
logger.info("failover debug ");
}
boolean isActive = loadClassIfActive(classLoader, clazz);
if (!isActive) {
return;
}
if (clazz.isAnnotationPresent(Adaptive.class)) {
cacheAdaptiveClass(clazz, overridden);
} else if (isWrapperClass(clazz)) {
cacheWrapperClass(clazz);
} else {
if (StringUtils.isEmpty(name)) {
name = findAnnotationName(clazz);
if (name.length() == 0) {
throw new IllegalStateException(
"No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
}
}
String[] names = NAME_SEPARATOR.split(name);
if (ArrayUtils.isNotEmpty(names)) {
cacheActivateClass(clazz, names[0]);
for (String n : names) {
cacheName(clazz, n);
saveInExtensionClass(extensionClasses, clazz, n, overridden);
}
}
}
}
这里进行了cache。
这个函数是被loadResource调用
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
java.net.URL resourceURL, boolean overridden,
String[] includedPackages, String[] excludedPackages,
String[] onlyExtensionClassLoaderPackages) {
try {
List<String> newContentList = getResourceContent(resourceURL);
String clazz;
for (String line : newContentList) {
Cluster load的extension 的resouce文件是
这是放在internal目录下,使用internal load Strategy优先load的。
dubbo 实际定了4种strategy,但DubboLoadingStrategy 没有被实际使用。
ServicesLoadingStrategy “META-INF/services/”
DubboExternalLoadingStrategy META-INF/dubbo/external/
DubboInternalLoadingStrategy META-INF/dubbo/internal/
DubboLoadingStrategy META-INF/dubbo/
是否wrapper,不是通过名称,而是通过构造函数,具体代码如下:
protected boolean isWrapperClass(Class<?> clazz) {
Constructor<?>[] constructors = clazz.getConstructors();
for (Constructor<?> constructor : constructors) {
if (constructor.getParameterTypes().length == 1 && constructor.getParameterTypes()[0] == type) {
return true;
}
}
return false;
}
而最后组装Cluster的代码如下:
if (CollectionUtils.isNotEmpty(wrapperClassesList)) {
for (Class<?> wrapperClass : wrapperClassesList) {
Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class);
boolean match = (wrapper == null) || ((ArrayUtils.isEmpty(
wrapper.matches()) || ArrayUtils.contains(wrapper.matches(),
name)) && !ArrayUtils.contains(wrapper.mismatches(), name));
if (match) {
instance = injectExtension(
(T) wrapperClass.getConstructor(type).newInstance(instance));
instance = postProcessAfterInitialization(instance, name);
}
}
}
以上的 newInstance就是第一张图中的调用过程。
注意是生成instance是下一个wrapper 类的构造函数的参数,最后返回的是最后一个wrapper类。
因此最后生成的类如下
如果配置了其它模式,如failfast,也是类似的。
PS class类无需加activate annotation,而filter必须有。