dubbo内核解析
dubbo的内核
dubbo所有功能都是基于dubbo内核之上完成的,dubbo内核由四部分构成,分别为SPI,Adaptive,Wrapper,Activate。
而dubbo的内核设计原则,也是我们所熟悉的aop,ioc与动态编译compiler,这些称之为dubbo的内核原理。
Adaptive
Adaptive 机制,即扩展类的自适应机制。即其可以指定想要加载的扩展名,也可以不指定。若不指定,则直接加载默认的扩展类。即其会自动匹配,做到自适应。其是通过@Adaptive注解实现的。
@Adaptive 注解
@Adaptive 注解可以修饰类与方法,其作用相差很大。
@Adaptive 类注解
实现的例子
接口和实现类继承SPI的例子添加Adaptive类
/**
* Adaptive类不属于Order的业务实现类。
* 本质上是对于功能接口的修饰类。
* 该类提供了Order接口的自适应取得方式
*/
@Adaptive
public class AdaptiveOrder implements Order {
// 支付方式
private String orderWay;
public String getOrderWay() {
return orderWay;
}
public void setOrderWay(String orderWay) {
this.orderWay = orderWay;
}
@Override
public void pay() {
// 取得类加载器
ExtensionLoader<Order> loader = ExtensionLoader.getExtensionLoader(Order.class);
Order order;
if (StringUtils.isEmpty(orderWay)) {
// 若没有指定则调用默认的扩展类即@SPI中指定的
order = loader.getDefaultExtension();
} else {
// 若指定则按照指定的功能性前缀进行加载
order = loader.getExtension(orderWay);
}
order.pay();
}
}
在服务提供者文件中添加
adaptive=com.demo.adaptive.service.impl.AdaptiveOrder
编写main方法
public class Main {
public static void main(String[] args) {
ExtensionLoader<Order> loader = ExtensionLoader.getExtensionLoader(Order.class);
AdaptiveOrder order =(AdaptiveOrder) loader.getAdaptiveExtension();
order.pay();
// 输出使用支付宝支付
}
}
跟踪源码总结生成过程
从缓存中取得ExtensionLoader,若不存在则创建ExtensionLoader并放入缓存中。
// private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();
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);
}
调用ExtensionLoader.getAdaptiveExtension尝试取得Adaptive类
public T getAdaptiveExtension() {
// 先查看Adaptive缓存是否已经生成
Object instance = cachedAdaptiveInstance.get();
if (instance == null) {
if (createAdaptiveInstanceError == null) {
// 双重检查锁
synchronized (cachedAdaptiveInstance) {
instance = cachedAdaptiveInstance.get();
if (instance == null) {
try {
// 没有生成的话,进行Adaptive的创建
instance = createAdaptiveExtension();
// 将创建好的类放入缓存
cachedAdaptiveInstance.set(instance);
} catch (Throwable t) {
createAdaptiveInstanceError = t;
throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);
}
}
}
} else {
throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);
}
}
// 返回Adaptive类实例
return (T) instance;
}
Adaptive类构建
private T createAdaptiveExtension() {
try {
// 构建过程在getAdaptiveExtensionClass中
// injectExtension为Adaptive类的依赖注入过程
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
} catch (Exception e) {
throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
}
Adaptive创建过程中体现出来@Adaptive在方法上与类上最大的区别
private Class<?> getAdaptiveExtensionClass() {
// 该流程与SPI一致即获取所有的服务提供者,并将有@Adaptive标识的类放入缓存
getExtensionClasses();
// 缓存不为空即存在有@Adaptive修饰的类直接返回该类的Class对象
if (cachedAdaptiveClass != null) {
return cachedAdaptiveClass;
}
// 不存在@Adaptive修饰的类则动态编译生成@Adaptive类
return cachedAdaptiveClass = createAdaptiveExtensionClass();
}
为Adaptive类中符合条件的属性进行依赖注入
- 类型为SPI修饰的功能性接口
- 该SPI接口必须含有@Adaptive修饰方法或者类
返回组装成功的Adaptive实例
@Adaptive 方法注解
实现的例子
服务接口
/**
* 该注解为标识注解,代表该类为SPI
* 且value值代表默认提供者为服务提供者文件中定义为alipay的服务实现类
*/
@SPI("alipay")
public interface Order {
@Adaptive
void pay(URL url);
}
提供者
import com.demo.adaptive.service.Order;
import org.apache.dubbo.common.URL;
public class AlipayOrder implements Order {
@Override
public void pay(URL url) {
System.out.println("使用支付宝支付");
}
}
import com.demo.adaptive.service.Order;
import org.apache.dubbo.common.URL;
public class WechatOrder implements Order {
@Override
public void pay(URL url) {
System.out.println("使用微信支付");
}
}
服务提供者文件
alipay=com.demo.adaptive.service.impl.AlipayOrder
wechat=com.demo.adaptive.service.impl.WechatOrder
编写main函数
public class Main {
public static void main(String[] args) {
ExtensionLoader<Order> loader = ExtensionLoader.getExtensionLoader(Order.class);
Order order = loader.getAdaptiveExtension();
order.pay(URL.valueOf("xxx://127.0.0.1/xxx?order=wechat"));
}
}
与类注解的区别
整体处理流程上是一致的唯一区别在于创建Adaptive类实例时,用的是动态编译生成了Adaptive类
下面是生成规则
package<SPI 接口所在包>;
public class SPI 接口名$Adpative implements SPI 接口 {
public adaptiveMethod(arg0, arg1, ...) {
// 注意,下面的判断仅对 URL 类型,或可以获取到 URL 类型值的参数进行判断
// 例如,dubbo 的 Invoker 类型中就包含有 URL 属性
if (arg1 == null) throw new IllegalArgumentException(异常信息);
if (arg1.getUrl() == null) throw new IllegalArgumentException(异常信息);
URL url = arg1.getUrl();
// 其会根据@Adaptive 注解上声明的 Key 的顺序,从 URL 获取 Value,
// 作为实际扩展类。若有默认扩展类,则获取默认扩展类名;否则获取
// 指定扩展名名。
String extName = url.get 接口名() == null ? 默认扩展前辍名 : url.get 接口名();
if (extName == null) throw new IllegalStateException(异常信息);
SPI 接口 extension = ExtensionLoader.getExtensionLoader(SPI 接口.class)
.getExtension(extName);
return extension.adaptiveMethod(arg0, arg1, ...);
}
public unAdaptiveMethod(arg0, arg1, ...) {
throw new UnsupportedOperationException(异常信息);
}
}
从这里也可以看出这里调用哪一个服务提供者是由URL中参数决定的。
- 如果参数没有指定,则调用SPI默认的服务提供者
- 如果指定了则根据服务提供者文件中定义的KEY去调用