上海营销网站建设公司,百度指数怎么看,广州购物必去的地方,wordpress直接大家好#xff0c;我是烤鸭#xff1a; 今天和大家分享dubbo的源码解析。 1.SPI 
http://dubbo.apache.org/zh-cn/docs/source_code_guide/dubbo-spi.html介绍: SPI 全称为 Service Provider Interface#xff0c;是一种服务发现机制。 SPI 的本质是将接口实现类的全限定名配…大家好我是烤鸭 今天和大家分享dubbo的源码解析。 1.SPI 
http://dubbo.apache.org/zh-cn/docs/source_code_guide/dubbo-spi.html介绍: SPI 全称为 Service Provider Interface是一种服务发现机制。 SPI 的本质是将接口实现类的全限定名配置在文件中并由服务加载器读取配置文件加载实现类。这样可以在运行时动态为接口替换实现类。 Dubbo重写了Java原生的SPI。Dubbo SPI 是通过键值对的方式进行配置按需加载指定的实现类。 源码com.alibaba.dubbo.common.extension.ExtensionLoader getExtension: 获取拓展类对象。 
createExtension: 1. 通过 getExtensionClasses 获取所有的拓展类 2. 通过反射创建拓展对象 3. 向拓展对象中注入依赖 injectExtension 4. 将拓展对象包裹在相应的 Wrapper 对象中 
将产生的wrapper对象放到 objectFactory 。 objectFactory 变量的类型为 AdaptiveExtensionFactoryAdaptiveExtensionFactory 内部维护了一个 ExtensionFactory 列表用于存储其他类型的 ExtensionFactory。Dubbo 目前提供了两种 ExtensionFactory分别是 SpiExtensionFactory 和 SpringExtensionFactory。前者用于创建自适应的拓展后者是用于从 Spring 的 IOC 容器中获取所需的拓展。  Dubbo IOC 目前仅支持 setter 方式注入。 
2.动态加载 
http://dubbo.apache.org/zh-cn/docs/source_code_guide/adaptive-extension.html 介绍: 拓展方法被调用时根据运行时参数进行加载。 Dubbo 会为拓展接口生成具有代理功能的代码。然后通过 javassist 或 jdk 编译这段代码得到 Class 类。最后再通过反射创建代理类整个过程比较复杂。 源码Adaptive  当 Adaptive 注解在类上时Dubbo 不会为该类生成代理类。注解在方法接口方法上时Dubbo 则会为该方法生成代理逻辑。 
com.alibaba.dubbo.common.extension.ExtensionLoader getAdaptiveExtension 创建自适应拓展。createAdaptiveExtension 1. 调用 getAdaptiveExtensionClass 方法获取自适应拓展 Class 对象 2. 通过反射进行实例化 3. 调用 injectExtension 方法向拓展实例中注入依赖 
getAdaptiveExtensionClass 1. 调用 getExtensionClasses 获取所有的拓展类 2. 检查缓存若缓存不为空则返回缓存 3. 若缓存为空则调用 createAdaptiveExtensionClass 创建自适应拓展类动态生成代码类 代码生成的顺序与 Java 文件内容顺序一致首先会生成 package 语句然后生成 import 语句紧接着生成类名等代码。 
// 生成 package 代码package  type 所在包
codeBuilder.append(package ).append(type.getPackage().getName()).append(;);
// 生成 import 代码import  ExtensionLoader 全限定名
codeBuilder.append(\nimport ).append(ExtensionLoader.class.getName()).append(;);
// 生成类代码public class  type简单名称  $Adaptive  implements  type全限定名  {
codeBuilder.append(\npublic class ).append(type.getSimpleName()).append($Adaptive).append( implements ).append(type.getCanonicalName()).append( {);// ${生成方法}codeBuilder.append(\n}); 
动态生成代码方法 Dubbo 不会为没有标注 Adaptive 注解的方法生成代理逻辑对于该种类型的方法仅会生成一句抛出异常的代码。 
for (Method method : methods) {// 省略无关逻辑Adaptive adaptiveAnnotation  method.getAnnotation(Adaptive.class);StringBuilder code  new StringBuilder(512);// 如果方法上无 Adaptive 注解则生成 throw new UnsupportedOperationException(...) 代码if (adaptiveAnnotation  null) {// 生成的代码格式如下// throw new UnsupportedOperationException(//     method   方法签名  of interface  全限定接口名  is not adaptive method!”)code.append(throw new UnsupportedOperationException(\method ).append(method.toString()).append( of interface ).append(type.getName()).append( is not adaptive method!\););} else {// 省略无关逻辑}// 省略无关逻辑
} 获取 URL 数据  要为 Protocol 接口的 refer 和 export 方法生成代理逻辑。  通过遍历 refer 的参数列表即可获取 URL 数据export 参数列表中没有 URL 参数因此需要从 Invoker 参数中获取 URL 数据。获取方式是调用 Invoker 中可返回 URL 的 getter 方法如果 Invoker 中无相关 getter 方法此时则会抛出异常。  生成后如下 refer:
if (arg1  null) throw new IllegalArgumentException(url  null);
com.alibaba.dubbo.common.URL url  arg1;export:
if (arg0  null) throw new IllegalArgumentException(com.alibaba.dubbo.rpc.Invoker argument  null);
if (arg0.getUrl()  null) throw new IllegalArgumentException(com.alibaba.dubbo.rpc.Invoker argument getUrl()  null);
com.alibaba.dubbo.common.URL url  arg0.getUrl(); 
获取 Adaptive 注解值 Adaptive 注解值 value 类型为 String[]可填写多个值默认情况下为空数组。若 value 为非空数组直接获取数组内容即可。若 value 为空数组则需进行额外处理。比如 LoadBalance 经过处理后得到 load.balance。 
检测 Invocation 参数 检测方法列表中是否存在 Invocation 类型的参数若存在则为其生成判空代码和其他一些代码。 
生成拓展名获取逻辑 本段逻辑用于根据 SPI 和 Adaptive 注解值生成“获取拓展名逻辑”同时生成逻辑也受 Invocation 类型参数影响综合因素导致本段逻辑相对复杂。本段逻辑可以会生成但不限于下面的代码 
String extName  (url.getProtocol()  null ? dubbo : url.getProtocol());
//或String extName  url.getMethodParameter(methodName, loadbalance, random);
//亦或是String extName  url.getParameter(client, url.getParameter(transporter, netty)); 
生成拓展加载与目标方法调用逻辑 本段代码逻辑用于根据拓展名加载拓展实例并调用拓展实例的目标方法。 以 Protocol 接口举例说明上面代码生成的内容如下 
com.alibaba.dubbo.rpc.Protocol extension  (com.alibaba.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
return extension.refer(arg0, arg1); 
生成完整的方法 以 Protocol 的 refer 方法为例上面代码生成的内容如下 
public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) {// 方法体
}