SPI机制源码

Dubbo常见SPI写法,表示获取black对应的Person接口扩展点,然后通过URL参数动态指定具体Person实现类中注入的Car的具体实例。

1
2
3
4
5
ExtensionLoader<Person> extensionLoader = ExtensionLoader.getExtensionLoader(Person.class);
Person person = extensionLoader.getExtension("black"); // BlackPerson
URL url = new URL(null, null, -1);
url = url.addParameter("car", "black");
System.out.println(person.getCar().getCarName(url)); // 代理逻辑

调用ExtensionLoadergetExtensionLoader方法时,首先从缓存中获取,若获取不到再通过传入的类创建一个新的ExtensionLoader且放入缓存中,在ExtensionLoader的构造方法中会通过getAdaptiveExtensionExtensionFactory中被@Adaptive注解标注的子类AdaptiveExtensionFactory作为objectFactory对象工厂,该工厂的作用是对SPI扩展类中有SPI扩展类作为属性Spring Bean作为属性的字段进行赋值,相当于Spring中的依赖注入。

getExtension方法中首先创建一个Holder类用于持有SPI实例,且使用其作为锁,防止两个线程同时获取同一个name扩展点对象的并发问题,且Holder会被放入cachedInstances缓存中。

然后调用createExtension方法创建扩展点实例对象,首先通过getExtensionClasses获取扩展类接口的所有实现类,然后根据名称获取具体的类,然后再通过injectExtension完成依赖注入,最后若该接口存在Wrapper,则遍历Wrapper调用其构造方法传入当前实例,然后对Wrapper进行依赖注入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public class ExtensionLoader<T> {
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();
private final Class<?> type; // 当前ExtensionLoader实例是哪个接口的扩展点加载器
private final ExtensionFactory objectFactory; // 扩展点工厂(对象工厂),可以获得某个对象
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)) {
throw new IllegalArgumentException("Extension type (" + type + ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
}
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
if (loader == null) {
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
}
return loader;
}
private ExtensionLoader(Class<?> type) {
this.type = type;
// objectFactory表示当前ExtensionLoader内部的一个对象工厂,可以用来获取对象AdaptiveExtensionFactory
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
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) { // 如果有两个线程同时来获取同一个name的扩展点对象,那只会有一个线程会进行创建
synchronized (holder) { // 一个name对应一把锁
instance = holder.get();
if (instance == null) { // 创建扩展点实例对象
instance = createExtension(name); // 创建扩展点对象
holder.set(instance);
}
}
}
return (T) instance;
}
private Holder<Object> getOrCreateHolder(String name) {
Holder<Object> holder = cachedInstances.get(name);
if (holder == null) {
cachedInstances.putIfAbsent(name, new Holder<>());
holder = cachedInstances.get(name);
}
return holder;
}
private T createExtension(String name) {
Class<?> clazz = getExtensionClasses().get(name); // 获取扩展类接口的所有实现类,然后根据名称获取具体的类
if (clazz == null) {
throw findException(name); // 找不到该名称对应的SPI扩展则抛异常
}
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz); // 实例缓存
if (instance == null) { // 创建实例
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
}
injectExtension(instance); // 依赖注入 IOC
Set<Class<?>> wrapperClasses = cachedWrapperClasses; // AOP,cachedWrapperClasses无序
if (CollectionUtils.isNotEmpty(wrapperClasses)) {
for (Class<?> wrapperClass : wrapperClasses) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
}
}
return instance;
} catch (Throwable t) {
throw new IllegalStateException("Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: " + t.getMessage(), t);
}
}
}

加载解析SPI文件

加载当前ExtensionLoader对象中指定的接口的所有扩展,首先还是从缓存中获取,若缓存中没有则再调用loadExtensionClasses方法加载到缓存中。首先通过cacheDefaultExtensionName方法获取SPI接口类上的@SPI注解,若该注解上设置了value属性,则将value属性中配置的值作为默认名称设置到cachedDefaultName属性中。

然后调用loadDirectory方法正则的加载SPI配置文件中的内容,加载顺序为META-INF/dubbo/internal/META-INF/dubbo/META-INF/services/但同一个接口在多个目录下配置了会被后面的补全覆盖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public class ExtensionLoader<T> {
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<?>> getExtensionClasses() {
// cachedClasses是一个Holder对象,持有的就是一个Map<String, Class<?>>是为了解决并发,Holder对象用来作为锁
Map<String, Class<?>> classes = cachedClasses.get();
if (classes == null) {
synchronized (cachedClasses) {
classes = cachedClasses.get();
if (classes == null) {
classes = loadExtensionClasses(); // 加载、解析文件Map
cachedClasses.set(classes);
}
}
}
return classes;
}
private Map<String, Class<?>> loadExtensionClasses() {
cacheDefaultExtensionName(); // cache接口默认的扩展类,给cachedDefaultName属性赋值
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;
}
private void cacheDefaultExtensionName() {
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
if (defaultAnnotation == null) {
return; // 若SPI接口上没有@SPI注解则直接跳过
}
String value = defaultAnnotation.value();
if ((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];
}
}
}
}

根据目录+SPI接口全限定名获取到具体的SPI配置文件URL列表,然后遍历按行读取文件内容,接忽略被#注释的部分,然后将名称和具体的实现类拆分开,反射得到具体的实现了的Class对象,首先若该实现类没有实现该指定的接口则抛出异常,然后判断若该实现类@Adaptive注解标注,则将其设置到cachedAdaptiveClass缓存中,且有且只能有一个实现类被@Adaptive注解标注否则抛出异常。

然后判断当前类是否有该接口作为唯一入参构造方法,以此判断是否为该接口的一个Wrapper类,若为Wrapper类将其加入到cachedWrapperClasses缓存中。

若该类既没有被@Adaptive注解标注也不是一个Wrapper类,则是一个普通的扩展类,首先通过findAnnotationName方法判断若该类被@Extension注解标注,则获取该注解的value属性配置的值作为实现类名称,若未被@Extension注解标注,获取当前加载类名称,若类名包含接口名将接口名截掉转为小写最终作为实现类名称。最后将类和名称缓存到cachedNamesextensionClasses中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type) {
String fileName = dir + type;
try {// 根据文件中的内容得到urls, 每个url表示一个扩展,如http=org.apache.dubbo.rpc.protocol.http.HttpProtocol
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()) { // 遍历url进行加载,把扩展类添加到extensionClasses中
java.net.URL resourceURL = urls.nextElement();
loadResource(extensionClasses, classLoader, resourceURL);
}
}
} catch (Throwable t) {
logger.error("Exception occurred when loading extension class (interface: " + type + ", description file: " + fileName + ").", t);
}
}
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {
try {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
String line;
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) { // 加载类,并添加到extensionClasses中
loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
}
} catch (Throwable t) {
IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
exceptions.put(line, e);
}
}
}
}
} catch (Throwable t) {
}
}
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
if (!type.isAssignableFrom(clazz)) { // 判断加载的类是否为当前type对应接口的实现类
throw new IllegalStateException("Error occurred when loading extension class (interface: " + type + ", class line: " + clazz.getName() + "), class " + clazz.getName() + " is not subtype of interface.");
}
if (clazz.isAnnotationPresent(Adaptive.class)) { // 判断当前类是否被@Adaptive注解标注
cacheAdaptiveClass(clazz); // 当前接口手动指定了Adaptive类
} else if (isWrapperClass(clazz)) {// 是一个Wrapper类
cacheWrapperClass(clazz); // 将当前类放入cachedWrapperClasses缓存中
} else { // 需要有无参的构造方法
clazz.getConstructor();
// 在文件中没有name,但是在类上指定了Extension的注解上指定了name
if (StringUtils.isEmpty(name)) {
name = findAnnotationName(clazz);
if (name.length() == 0) { // 若name未指定则抛异常
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]); // 缓存一下被Activate注解了的类
for (String n : names) { // 有多个名字
cacheName(clazz, n); // clazz: name放入cachedNames
saveInExtensionClass(extensionClasses, clazz, n); // name: clazz放入extensionClasses
}
}
}
}
private void cacheAdaptiveClass(Class<?> clazz) {
if (cachedAdaptiveClass == null) {
cachedAdaptiveClass = clazz;
} else if (!cachedAdaptiveClass.equals(clazz)) {
throw new IllegalStateException("More than 1 adaptive class found: " + cachedAdaptiveClass.getName() + ", " + clazz.getName());
}
}
private boolean isWrapperClass(Class<?> clazz) {
try { // 通过该类是否有改接口的构造方法判断是否为一个Wrapper类
clazz.getConstructor(type);
return true;
} catch (NoSuchMethodException e) {
return false;
}
}
private void cacheWrapperClass(Class<?> clazz) {
if (cachedWrapperClasses == null) {
cachedWrapperClasses = new ConcurrentHashSet<>();
}
cachedWrapperClasses.add(clazz);
}
private String findAnnotationName(Class<?> clazz) {
org.apache.dubbo.common.Extension extension = clazz.getAnnotation(org.apache.dubbo.common.Extension.class);
if (extension != null) {
return extension.value();
}
String name = clazz.getSimpleName();
if (name.endsWith(type.getSimpleName())) { // 若未被@Extension注解标注,获取当前加载类名称,若类名包含接口名则将接口名截掉
name = name.substring(0, name.length() - type.getSimpleName().length());
}
return name.toLowerCase(); // 转换为小写
}
private void cacheName(Class<?> clazz, String name) {
if (!cachedNames.containsKey(clazz)) {
cachedNames.put(clazz, name);
}
}
private void saveInExtensionClass(Map<String, Class<?>> extensionClasses, Class<?> clazz, String name) {
Class<?> c = extensionClasses.get(name);
if (c == null) {
extensionClasses.put(name, clazz);
} else if (c != clazz) {
String duplicateMsg = "Duplicate extension " + type.getName() + " name " + name + " on " + c.getName() + " and " + clazz.getName();
throw new IllegalStateException(duplicateMsg);
}
}
private void cacheActivateClass(Class<?> clazz, String name) {
Activate activate = clazz.getAnnotation(Activate.class); // 类上Activate注解
if (activate != null) {
cachedActivates.put(name, activate);
} else {// support com.alibaba.dubbo.common.extension.Activate
com.alibaba.dubbo.common.extension.Activate oldActivate = clazz.getAnnotation(com.alibaba.dubbo.common.extension.Activate.class);
if (oldActivate != null) {
cachedActivates.put(name, oldActivate);
}
}
}

依赖注入

依赖注入首先判断方法若不是setter方法直接跳过,若不想被依赖注入可在setter方法上通过@DisableInject注解标注,且若当前方法是Void、Boolean、Byte、Integer等基本数据类型StringNumber的子类Date的子类等则不需要做依赖注入直接跳过,然后解析setter方法获取到需要依赖注入的属性的属性名,然后通过在构造方法中得到的AdaptiveExtensionFactory工厂获取具体的属性值。通过反射注入到实例中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
private T injectExtension(T instance) {
if (objectFactory == null) {
return instance;
}
try {
for (Method method : instance.getClass().getMethods()) {
if (!isSetter(method)) {
continue; // 若不是setter方法直接跳过
}
if (method.getAnnotation(DisableInject.class) != null) { // 利用set方法注入
continue; // 若该方法被@DisableInject注解标注则跳过
}
// set方法中的参数类型
Class<?> pt = method.getParameterTypes()[0]; // Person接口
if (ReflectUtils.isPrimitives(pt)) {
continue; // 若当前方法是9种基本数据类型、String、Number的之类、Date的子类等则不需要做依赖注入,直接跳过
}
try {
String property = getSetterProperty(method); // 得到setXxx中的xxx
// 根据参数类型或属性名,从objectFactory中获取到对象,然后调用set方法进行注入,AdaptiveExtensionFactory
Object object = objectFactory.getExtension(pt, property); // User.class, user
if (object != null) {
method.invoke(instance, object); // 反射调用setter方法赋值
}
} catch (Exception e) {
}
}
} catch (Exception e) {
}
return instance;
}
private String getSetterProperty(Method method) {
return method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
}
private boolean isSetter(Method method) {
return method.getName().startsWith("set")
&& method.getParameterTypes().length == 1
&& Modifier.isPublic(method.getModifiers());
}

在实力化AdaptiveExtensionFactory时通过构造方法将所以未被@Adaptive注解标注的类加载到factories中,Dubbo内置就SpiExtensionFactorySpringExtensionFactory分别用于注入SPI扩展实例和Spring中的Bean,当然也可以通过SPI机制扩展ExtensionFactory,在getExtension方法中遍历这些扩展类获取到具体的实例对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {
private final List<ExtensionFactory> factories;
public AdaptiveExtensionFactory() { // 支持哪些ExtensionFactory (Spi, SPring)
ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
for (String name : loader.getSupportedExtensions()) { // spi, spring
list.add(loader.getExtension(name));
}
factories = Collections.unmodifiableList(list);
}
@Override
public <T> T getExtension(Class<T> type, String name) {
// 遍历两个ExtensionFactory,从ExtensionFactory中得到实例,只要从某个ExtensionFactory中获取到对象实例就可以了
for (ExtensionFactory factory : factories) {
T extension = factory.getExtension(type, name); // SpringExtensionFactory,SpiExtensionFactory
if (extension != null) {
return extension;
}
}
return null;
}
}

SPI机制若type类被@Adaptive注解标记则直接返回该类,否则通过AdaptiveClassCodeGenerator给当前类创建一个代理类代码,然后编译成一个Class对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
public class SpiExtensionFactory implements ExtensionFactory {
@Override
public <T> T getExtension(Class<T> type, String name) { // 接口上存在SPI注解
if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
if (!loader.getSupportedExtensions().isEmpty()) {
return loader.getAdaptiveExtension(); // 接口的Adaptive类(代理对象)
}
}
return null;
}
}
public class ExtensionLoader<T> {
public T getAdaptiveExtension() {
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
if (createAdaptiveInstanceError != null) {
throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
}
synchronized (cachedAdaptiveInstance) {
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
instance = createAdaptiveExtension();
cachedAdaptiveInstance.set(instance);
} catch (Throwable t) {
createAdaptiveInstanceError = t;
throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t);
}
}
}
}
return (T) instance;
}
private T createAdaptiveExtension() {
try { // 首先获取到该实例的代理对象,然后给代理对象依赖注入
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
private Class<?> getAdaptiveExtensionClass() {
getExtensionClasses(); // 获取当前接口的所有扩展类
if (cachedAdaptiveClass != null) { // 缓存了@Adaptive注解标记的类
return cachedAdaptiveClass;
}
// 如果某个接口没有手动指定一个Adaptive类,那么就自动生成一个Adaptive类
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
rivate Class<?> createAdaptiveExtensionClass() {
// cachedDefaultName表示接口默认的扩展类
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);
}
}

类中没有被@Adaptive注解标注的方法则直接抛出异常,并不是所有的方法都会生成代理,只有方法上被@Adaptive注解标注了才会生成代理,未被@Adaptive注解标注方法生成的方法中直接抛出一个异常,在通过generateExtNameAssignment构建方法代码时在会生成通过URL做相应处理的内容,所以被@Adaptive标注的方法必须有一个URL参数或对应的参数类中存在getUrl方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
public class AdaptiveClassCodeGenerator {
private boolean hasAdaptiveMethod() {
return Arrays.stream(type.getMethods()).anyMatch(m -> m.isAnnotationPresent(Adaptive.class));
}
public String generate() {
if (!hasAdaptiveMethod()) {
throw new IllegalStateException("No adaptive method exist on extension " + type.getName() + ", refuse to create the adaptive class!");
}
StringBuilder code = new StringBuilder();
code.append(generatePackageInfo());
code.append(generateImports());
code.append(generateClassDeclaration());
Method[] methods = type.getMethods();
for (Method method : methods) { // 遍历接口中的方法,生成代理方法
code.append(generateMethod(method));
}
code.append("}");
return code.toString();
}
private String generateMethod(Method method) {
String methodReturnType = method.getReturnType().getCanonicalName();
String methodName = method.getName();
String methodContent = generateMethodContent(method);
String methodArgs = generateMethodArguments(method);
String methodThrows = generateMethodThrows(method);
return String.format(CODE_METHOD_DECLARATION, methodReturnType, methodName, methodArgs, methodThrows, methodContent);
}
private String generateMethodContent(Method method) { // 方法上存在Adaptive注解才进行代理
Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);
StringBuilder code = new StringBuilder(512);
if (adaptiveAnnotation == null) {
return generateUnsupported(method); // 方法内直接抛出异常
} else { // 方法中URL类型参数的下标
int urlTypeIndex = getUrlTypeIndex(method);
// 寻找URL:1.如果当前方法中有URl类型的参数,那么url就是该参数值
// 2.如果当前方法中没有URL类型的参数,但是当前方法中有某个类型中的get方法返回了URl类型,那么就调用那个get方法得到一个url对象
if (urlTypeIndex != -1) {// Null Point check
code.append(generateUrlNullCheck(urlTypeIndex));
} else {// did not find parameter in URL type
code.append(generateUrlAssignmentIndirectly(method));
}
String[] value = getMethodAdaptiveValue(adaptiveAnnotation); // 根据这个value去找具体的扩展类
boolean hasInvocation = hasInvocationArgument(method); // 方法中有Invocation类型的参数
code.append(generateInvocationArgumentNullCheck(method));
code.append(generateExtNameAssignment(value, hasInvocation));
code.append(generateExtNameNullCheck(value)); // check extName == null?
code.append(generateExtensionAssignment());
code.append(generateReturnAndInvocation(method)); // return statement
}
return code.toString();
}
private String generateExtNameAssignment(String[] value, boolean hasInvocation) {
// TODO: refactor it
String getNameCode = null;
for (int i = value.length - 1; i >= 0; --i) {
if (i == value.length - 1) {
if (null != defaultExtName) {
if (!"protocol".equals(value[i])) {
if (hasInvocation) {
getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
} else {
getNameCode = String.format("url.getParameter(\"%s\", \"%s\")", value[i], defaultExtName);
}
} else {
getNameCode = String.format("( url.getProtocol() == null ? \"%s\" : url.getProtocol() )", defaultExtName);
}
} else {
if (!"protocol".equals(value[i])) {
if (hasInvocation) {
getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
} else {
getNameCode = String.format("url.getParameter(\"%s\")", value[i]);
}
} else {
getNameCode = "url.getProtocol()";
}
}
} else {
if (!"protocol".equals(value[i])) {
if (hasInvocation) {
getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
} else {
getNameCode = String.format("url.getParameter(\"%s\", %s)", value[i], getNameCode);
}
} else {
getNameCode = String.format("url.getProtocol() == null ? (%s) : url.getProtocol()", getNameCode);
}
}
}
return String.format(CODE_EXT_NAME_ASSIGNMENT, getNameCode);
}
}

生成的代理对象代码示例如下,很明显在代理方法中也是通过SPI加载机制来获取实例,可以通过传入URL参数且通过其addParameter方法给URL对象设置参数来动态选择实例对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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.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);
}

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);
}
}
package com.eleven.icode;
import org.apache.dubbo.common.extension.ExtensionLoader;
public class Car$Adaptive implements com.eleven.icode.Car {
public java.lang.String getCarName(org.apache.dubbo.common.URL arg0) {
if (arg0 == null) throw new IllegalArgumentException("url == null");
org.apache.dubbo.common.URL url = arg0;
String extName = url.getParameter("car");
if(extName == null)
throw new IllegalStateException("Failed to get extension (com.eleven.icode.Car) name from url (" + url.toString() + ") use keys([car])");
com.eleven.icode.Car extension = (com.eleven.icode.Car)ExtensionLoader.getExtensionLoader(com.eleven.icode.Car.class).getExtension(extName);
return extension.getCarName(arg0);
}
public java.lang.String sayHell() {
throw new UnsupportedOperationException("The method public abstract java.lang.String com.eleven.icode.Car.sayHell() of interface com.eleven.icode.Car is not adaptive method!");
}
}

对于Spring的依赖注入优先通过Bean的名称从Spring容器中获取具体的Bean,若通过名称未找到则再通过类型从Spring容器中获取实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class SpringExtensionFactory implements ExtensionFactory {
public <T> T getExtension(Class<T> type, String name) {
if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
return null; // 若接口上存在SPI注解,就不从Spring中获取对象实例了
}
for (ApplicationContext context : CONTEXTS) {
if (context.containsBean(name)) {
Object bean = context.getBean(name); // 从ApplicationContext中获取bean, byname
if (type.isInstance(bean)) {
return (T) bean;
}
}
}
if (Object.class == type) {
return null;
}
for (ApplicationContext context : CONTEXTS) {
try {
return context.getBean(type); // byType
} catch (NoUniqueBeanDefinitionException multiBeanExe) {
} catch (NoSuchBeanDefinitionException noBeanExe) {
}
}
return null;
}
}

若不想使用Dubbo通过代码生成的Adaptive类也可以自定义一个Adaptive类,即实现接口且在该类上加上@Adaptive注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Adaptive
public class AdaptiveCar implements Car {
public Car getExtension(Class<Car> type, String name) {
return new RedCar();
}
@Override
public String getCarName(URL url) {
return "这是一个Adaptive标注的类";
}
@Override
public String sayHell() {
return null;
}
}