Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit a9f25b0

Browse filesBrowse files
committed
[U] 更新Dubbo SPI
1 parent 948b1ed commit a9f25b0
Copy full SHA for a9f25b0

File tree

Expand file treeCollapse file tree

2 files changed

+62
-4
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

2 files changed

+62
-4
lines changed
Open diff view settings
Collapse file

‎note/Dubbo/Dubbo底层源码学习(二)—— Dubbo的SPI机制(下).md‎

Copy file name to clipboardExpand all lines: note/Dubbo/Dubbo底层源码学习(二)—— Dubbo的SPI机制(下).md
+62-4Lines changed: 62 additions & 4 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -213,15 +213,72 @@ getExtensionLoader方法首先回去判断EXTENSION_LOADERS缓存中是否已经
213213

214214
### 2. @Adaptive注解
215215

216-
AdaptiveExtensionFactory 不实现任何具体的功能,而是用来适配 ExtensionFactory 的 SpiExtensionFactory 和 SpringExtensionFactory 这两种实现。AdaptiveExtensionFactory 会根据运行时的一些状态来选择具体调用 ExtensionFactory 的哪个实现。
216+
@Adaptive注解来实现Dubbo的适配器功能。在Dubbo中,ExtensionFactory接口有三种实现,如下图:
217+
218+
![SPI_ADAPTIVE](https://github.com/coderbruis/JavaSourceCodeLearning/blob/master/note/images/Dubbo/spi_@Adaptive.png)
219+
220+
在ExtensionFactory接口上有@SPI注解修饰,而Dubbo会在调用ExtensionFactory时,会去调用ExtensionFactory的SPI配置文件中的扩展点名称以及扩展点实现类,查看下其SPI配置文件:
221+
```
222+
adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory
223+
spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory
224+
```
225+
226+
那上图中的AdaptiveExtensionFactory、SpiExtensionFactory、SpringExtensionFactory之间是什么关系呢?和@Adaptive又有什么关联?
227+
228+
首先,AdaptiveExtensionFactory是不实现任何具体的功能,是用来适配 ExtensionFactory 的 SpiExtensionFactory 和 SpringExtensionFactory 这两种实现。AdaptiveExtensionFactory 会根据运行时的一些状态来选择具体调用 ExtensionFactory 的哪个实现。
217229

218230
AdaptiveExtensionFactory会根据运行时状态来决定给ExtensionFactory赋值哪个实现,例如在Dubbo源码本地,使用的是SpiExtensionFactory这个类,而如果
219231
是在Spring环境的话,则会使用SpringExtensionFactory这种实现。适配核心逻辑在AdaptiveExtensionFactory的构造方法里。
220232

233+
下面看下AdaptiveExtensionFactory类:
234+
235+
```
236+
@Adaptive
237+
public class AdaptiveExtensionFactory implements ExtensionFactory {
238+
239+
// 需要真正调用的ExtensionFactory对象
240+
private final List<ExtensionFactory> factories;
241+
242+
public AdaptiveExtensionFactory() {
243+
// 获取ExtensionFactory这个扩展点的扩展加载器
244+
ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
245+
List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
246+
for (String name : loader.getSupportedExtensions()) { // ------------------------ ①
247+
// 去获取ExtensionFactory的SPI扩展点实现类, 所以这里一般都是获取的是SpiExtensionFactory
248+
list.add(loader.getExtension(name));
249+
}
250+
// 因而AdaptiveExtensionFactory的factories属性值为SpiExtensionFactory。当然如果是Spring环境的话,则会适配到SpringExtensionFactory
251+
factories = Collections.unmodifiableList(list);
252+
System.err.println("AdaptiveExtensionFactory....");
253+
}
254+
255+
@Override
256+
public <T> T getExtension(Class<T> type, String name) {
257+
for (ExtensionFactory factory : factories) {
258+
// 遍历factories集合,然后调用ExtensionFactory实现类的getExtension()方法
259+
T extension = factory.getExtension(type, name);
260+
if (extension != null) {
261+
return extension;
262+
}
263+
}
264+
return null;
265+
}
266+
267+
}
268+
```
269+
270+
① 中逻辑是这样的,调用ExtensionLoader#getSupportedExtensions()回去加载ExtensionFactory所有的扩展点实现类,并返回一个扩展点名称作为Key,扩展点实现类Class对象为Value的Map集合,
271+
在上面的SPI配置文件中已经展示出来了,所以这里获取到的是spi。
272+
273+
// 有人可能会问,上面的SPI配置文件不是还有一个adaptive吗?为什么没加载进来呢?这是因为getSupportedExtension()中实际是调用getExtensionClasses()方法去获取Map集合,而其底层是去从cachedClasses缓存中
274+
获取,而adaptive扩展点实现类是缓存在了cachedAdaptiveClass中的。
275+
276+
277+
下面看看ExtensionLoader的方法:
221278
```
222279
private Class<?> getAdaptiveExtensionClass() {
223280
// 获取扩展点实现类,如果缓存中没有则去扫描SPI文件,扫描到扩展点实现类后则存入cachedClasses缓存中
224-
getExtensionClasses(); // ------------------------
281+
getExtensionClasses(); // ------------------------
225282
if (cachedAdaptiveClass != null) {
226283
return cachedAdaptiveClass;
227284
}
@@ -240,7 +297,7 @@ AdaptiveExtensionFactory会根据运行时状态来决定给ExtensionFactory赋
240297
// 如果加载的扩展点实现类中有@Adaptive注解修饰,则将该类缓存到cachedAdaptiveClass缓存中
241298
// 而如果对于有@Adaptive修饰的接口,并且修饰在了方法上,没有@Adaptive注解修饰的扩展点实现类的话,则会通过Javassist生成代理代码,生成对于的自适应逻辑
242299
if (clazz.isAnnotationPresent(Adaptive.class)) {
243-
cacheAdaptiveClass(clazz, overridden); // ------------------------
300+
cacheAdaptiveClass(clazz, overridden); // ------------------------
244301
} else if (isWrapperClass(clazz)) { // 判断是否是包装类,判断依据是:该扩展实现类是否包含拷贝构造函数(即构造函数只有一个参数且为扩展接口类型)
245302
cacheWrapperClass(clazz);
246303
} else {
@@ -264,9 +321,10 @@ AdaptiveExtensionFactory会根据运行时状态来决定给ExtensionFactory赋
264321
}
265322
```
266323

267-
中会去加载扩展点实现类,然后将所有的扩展点都加载然后缓存到对应的缓存中,当程序走到了时,会判断扩展点实现类是否有@Adaptive注解修饰,如果有的话就会将其实现类缓存到cachedAdaptiveClass中;否则在中判断到cachedAdaptiveClass中没有缓存的实现类,就表示没有@Adaptive修饰
324+
中会去加载扩展点实现类,然后将所有的扩展点都加载然后缓存到对应的缓存中,当程序走到了时,会判断扩展点实现类是否有@Adaptive注解修饰,如果有的话就会将其实现类缓存到cachedAdaptiveClass中;否则在中判断到cachedAdaptiveClass中没有缓存的实现类,就表示没有@Adaptive修饰
268325
的扩展点实现类,就会去通过Javassist来生成代理代码,即生成对于的Xxx@Adaptive代码。
269326

327+
下面就是通过Javassist代理生产的适配类。(再Dubbo源码中的dubbo-common模块test目录下的org.apache.dubbo.extension包中有对应的测试类)
270328
```
271329
package org.apache.dubbo.common.extension.ext1;
272330
Collapse file
13 KB
  • Display the source diff
  • Display the rich diff
Loading

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.