mirror of
https://github.com/youthlql/JavaYouth.git
synced 2026-04-18 17:03:40 +00:00
小更新,可忽略
This commit is contained in:
@@ -13,16 +13,18 @@ abbrlink: dbcfef47
|
||||
date: 2021-09-12 15:21:58
|
||||
---
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 第三节: Dubbo的可扩展机制SPI源码解析
|
||||
|
||||
|
||||
|
||||
dubbo源码项目地址:[https://gitee.com/archguide/dubbovip](https://gitee.com/archguide/dubbovip)
|
||||
|
||||
### 笔记更新地址:
|
||||
|
||||
[https://www.yuque.com/books/share/f2394ae6-381b-4f44-819e-c231b39c1497](https://www.yuque.com/books/share/f2394ae6-381b-4f44-819e-c231b39c1497?#)(密码:kyys) 《Dubbo笔记》
|
||||
|
||||
|
||||
|
||||
### SPI的概念
|
||||
|
||||
https://www.cnblogs.com/happyframework/archive/2013/09/17/3325560.html
|
||||
@@ -44,24 +46,24 @@ spi-demo
|
||||
| | ├── main/
|
||||
| | | ├── java/
|
||||
| | | | └── com/
|
||||
| | | | └── youthlql/
|
||||
| | | | └── atguigu/
|
||||
| | | | └── mysql/
|
||||
| | | | └── MySQLSaveService.java
|
||||
| | | └── resources/
|
||||
| | | └── META-INF/
|
||||
| | | └── services/
|
||||
| | | └── com.youthlql.data.DataSaveService
|
||||
| | | └── com.atguigu.data.DataSaveService
|
||||
| | └── test/
|
||||
| | └── java/
|
||||
| └── target/
|
||||
| ├── classes/
|
||||
| | ├── com/
|
||||
| | | └── youthlql/
|
||||
| | | └── atguigu/
|
||||
| | | └── mysql/
|
||||
| | | └── MySQLSaveService.class
|
||||
| | └── META-INF/
|
||||
| | └── services/
|
||||
| | └── com.youthlql.data.DataSaveService
|
||||
| | └── com.atguigu.data.DataSaveService
|
||||
| └── generated-sources/
|
||||
| └── annotations/
|
||||
├── api-db-impl-redis/
|
||||
@@ -71,24 +73,24 @@ spi-demo
|
||||
| | ├── main/
|
||||
| | | ├── java/
|
||||
| | | | └── com/
|
||||
| | | | └── youthlql/
|
||||
| | | | └── atguigu/
|
||||
| | | | └── redis/
|
||||
| | | | └── RedisSaveService.java
|
||||
| | | └── resources/
|
||||
| | | └── META-INF/
|
||||
| | | └── services/
|
||||
| | | └── com.youthlql.data.DataSaveService
|
||||
| | | └── com.atguigu.data.DataSaveService
|
||||
| | └── test/
|
||||
| | └── java/
|
||||
| └── target/
|
||||
| ├── classes/
|
||||
| | ├── com/
|
||||
| | | └── youthlql/
|
||||
| | | └── atguigu/
|
||||
| | | └── redis/
|
||||
| | | └── RedisSaveService.class
|
||||
| | └── META-INF/
|
||||
| | └── services/
|
||||
| | └── com.youthlql.data.DataSaveService
|
||||
| | └── com.atguigu.data.DataSaveService
|
||||
| └── generated-sources/
|
||||
| └── annotations/
|
||||
├── api-db-interface/
|
||||
@@ -98,7 +100,7 @@ spi-demo
|
||||
| | ├── main/
|
||||
| | | ├── java/
|
||||
| | | | └── com/
|
||||
| | | | └── youthlql/
|
||||
| | | | └── atguigu/
|
||||
| | | | └── data/
|
||||
| | | | └── DataSaveService.java
|
||||
| | | └── resources/
|
||||
@@ -107,7 +109,7 @@ spi-demo
|
||||
| └── target/
|
||||
| ├── classes/
|
||||
| | └── com/
|
||||
| | └── youthlql/
|
||||
| | └── atguigu/
|
||||
| | └── data/
|
||||
| | └── DataSaveService.class
|
||||
| └── generated-sources/
|
||||
@@ -119,7 +121,7 @@ spi-demo
|
||||
| | ├── main/
|
||||
| | | ├── java/
|
||||
| | | | └── com/
|
||||
| | | | └── youthlql/
|
||||
| | | | └── atguigu/
|
||||
| | | | └── redis/
|
||||
| | | | └── MainTest.java
|
||||
| | | └── resources/
|
||||
@@ -128,7 +130,7 @@ spi-demo
|
||||
| └── target/
|
||||
| ├── classes/
|
||||
| | └── com/
|
||||
| | └── youthlql/
|
||||
| | └── atguigu/
|
||||
| | └── redis/
|
||||
| | └── MainTest.class
|
||||
| └── generated-sources/
|
||||
@@ -143,7 +145,7 @@ spi-demo
|
||||
#### MainTest
|
||||
|
||||
```java
|
||||
import com.youthlql.data.DataSaveService;
|
||||
import com.atguigu.data.DataSaveService;
|
||||
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
@@ -222,18 +224,18 @@ public class RedisSaveService implements DataSaveService {
|
||||
|
||||
#### SPI文件示例
|
||||
|
||||
api-db-impl-redis\src\main\resources\META-INF\services\com.youthlql.data.DataSaveService
|
||||
api-db-impl-redis\src\main\resources\META-INF\services\com.atguigu.data.DataSaveService
|
||||
|
||||
```txt
|
||||
com.youthlql.redis.RedisSaveService
|
||||
com.atguigu.redis.RedisSaveService
|
||||
```
|
||||
|
||||
|
||||
|
||||
api-db-impl-mysql\src\main\resources\META-INF\services\com.youthlql.data.DataSaveService
|
||||
api-db-impl-mysql\src\main\resources\META-INF\services\com.atguigu.data.DataSaveService
|
||||
|
||||
```txt
|
||||
com.youthlql.mysql.MySQLSaveService
|
||||
com.atguigu.mysql.MySQLSaveService
|
||||
```
|
||||
|
||||
你没看错就是这么简单
|
||||
@@ -253,9 +255,9 @@ com.youthlql.mysql.MySQLSaveService
|
||||
SPI文件里写了什么,java的`ServiceLoader`都会给你一次性加载完
|
||||
|
||||
```java
|
||||
com.youthlql.RedCar
|
||||
com.youthlql.BlackCar
|
||||
com.youthlql,WhiteCar
|
||||
com.tuling.RedCar
|
||||
com.tuling.BlackCar
|
||||
com.tuling,WhiteCar
|
||||
....
|
||||
```
|
||||
|
||||
@@ -275,8 +277,8 @@ com.youthlql,WhiteCar
|
||||
spi文件我们可以这样写:
|
||||
|
||||
```java
|
||||
red=com.youthlql.RedCar
|
||||
black=com.youthlql.BlackCar
|
||||
red=com.tuling.RedCar
|
||||
black=com.tuling.BlackCar
|
||||
```
|
||||
|
||||
`SpiTest.java`
|
||||
@@ -354,6 +356,10 @@ System.out.println(http);
|
||||
|
||||
|
||||
|
||||
### Dubbo SPI 架构图
|
||||
|
||||
<img src="https://npm.elemecdn.com/youthlql@1.0.3/rpc/dubbo/v1/03_di_san_jie/Dubbo-SPI架构图.png"/>
|
||||
|
||||
|
||||
|
||||
### ExtensionLoader源码
|
||||
@@ -400,6 +406,8 @@ System.out.println(http);
|
||||
|
||||
后续,在A接口的代理对象被真正用到时,才会结合URL信息找到真正的A接口对应的扩展点实例进行调用。
|
||||
|
||||
<img src="https://npm.elemecdn.com/youthlql@1.0.3/rpc/dubbo/v1/03_di_san_jie/ExtensionLoader.png"/>
|
||||
|
||||
|
||||
|
||||
#### getExtension()
|
||||
@@ -659,9 +667,9 @@ loadResource方法就是完成对文件内容的解析,按行进行解析,
|
||||
clazz.getConstructor();
|
||||
|
||||
/*
|
||||
1. 本来应该这样写的 red=com.youthlql.RedCar
|
||||
2.如果你前面的red这个name没写,像这样只写了个全类名com.youthlql.RedCar
|
||||
3.默认会去com.youthlql.RedCar这个类上找有没有@Extension注解起名了【官方已经标记成废弃了】
|
||||
1. 本来应该这样写的 red=com.tuling.RedCar
|
||||
2.如果你前面的red这个name没写,像这样只写了个全类名com.tuling.RedCar
|
||||
3.默认会去com.tuling.RedCar这个类上找有没有@Extension注解起名了【官方已经标记成废弃了】
|
||||
*/
|
||||
if (StringUtils.isEmpty(name)) {
|
||||
name = findAnnotationName(clazz);
|
||||
@@ -966,9 +974,9 @@ public class SpiExtensionFactory implements ExtensionFactory {
|
||||
|
||||
|
||||
|
||||
dubbo生成的代理对象代码可以看下面的`自适应扩展点补充`,这里应该就知道为什么要用URL了
|
||||
|
||||
dubbo生成的代理对象截图,这里应该就知道为什么要用URL了
|
||||
|
||||
<img src="https://npm.elemecdn.com/youthlql@1.0.3/rpc/dubbo/v1/03_di_san_jie/image-20210904210634167.png"/>
|
||||
|
||||
```java
|
||||
public class DubboIOCTest {
|
||||
@@ -1044,7 +1052,7 @@ dubbo中也实现了一套非常简单的AOP,就是利用Wrapper,如果一
|
||||
|
||||
```
|
||||
|
||||
|
||||
<img src="https://npm.elemecdn.com/youthlql@1.0.3/rpc/dubbo/v1/03_di_san_jie/createExtension.png"/>
|
||||
|
||||
### 自适应扩展点补充
|
||||
|
||||
@@ -1067,7 +1075,7 @@ Protocol protocol = extensionLoader.getAdaptiveExtension();
|
||||
|
||||
|
||||
|
||||
再看个例子,Protocol接口的Adaptive类的代理:
|
||||
再看个例子,Protocol接口的Adaptive类代理:
|
||||
|
||||
```java
|
||||
package org.apache.dubbo.rpc;
|
||||
@@ -1130,9 +1138,9 @@ public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {
|
||||
|
||||
|
||||
|
||||
所以,可以发现,某个接口的Adaptive对象,在调用某个方法时,是通过该方法中的URL参数或者getURL方法,通过调用ExtensionLoader.getExtensionLoader(com.luban.Car.class).getExtension(extName);得到一个扩展点实例,然后调用该实例对应的方法。
|
||||
|
||||
所以,可以发现,某个接口的Adaptive对象,在调用某个方法时,是通过该方法中的URL参数或者getUrl方法,通过调用ExtensionLoader.getExtensionLoader(com.luban.Car.class).getExtension(extName);得到一个扩展点实例,然后调用该实例对应的方法。
|
||||
|
||||
|
||||
|
||||
### Activate扩展点
|
||||
|
||||
|
||||
Reference in New Issue
Block a user