-
Dubbo基于Spring 的Schema扩展进行加载
- 元素介绍
- complexType:元素定义复杂类型
- sequence:要求组中的元素以指定顺序出现在包含元素中,每个子元素可出现0到任意次
- annotation:顶级元素,规定schema的注释
<annotation id=ID any attributes > (appinfo|documentation)* </annotation>
- complexType:元素定义复杂类型
- 自定义配置步骤
- 设计配置属性和JavaBean
- 编写XSD文件
- 编写NamespaceHandler和BeanDefinitionParser完成解析工作
- 编写spring.handlers和spring.schemas串联起所有部件
- 在Bean文件中应用
- 元素介绍
-
SPI(服务发现机制)
- 本质:将接口实现类的全限定名配置在文件中 --> 由加载器读取配置文件(加载实现类) --> 运行时为接口替换实现类
- 通过SPI机制为程序提供拓展功能,Dubbo增强了JAVA SPI机制
- Dubbo SPI所需的配置文件需放置在META-INF/dubbo
- 通过ExtensionLoader加载指定实现类,配置文件需放置在META-INF/dubbo
- 支持按需加载接口实现类,还增加了IOC和AOP等特性
package com.examle.core.rpc; import com.examle.core.common.extension.ExtensionLoader; public class ProxyFactory$Adaptive implements com.examle.core.rpc.ProxyFactory { public com.examle.core.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, com.examle.core.common.URL arg2) throws com.examle.core.rpc.RpcException { if (arg2 == null) throw new IllegalArgumentException("url == null"); com.examle.core.common.URL url = arg2; String extName = url.getParameter("proxy", "javassist"); if(extName == null) throw new IllegalStateException("Fail to get extension(com.examle.core.rpc.ProxyFactory) name from url(" + url.toString() + ") use keys([proxy])"); com.examle.core.rpc.ProxyFactory extension = (com.examle.core.rpc.ProxyFactory)ExtensionLoader.getExtensionLoader(com.examle.core.rpc.ProxyFactory.class).getExtension(extName); return extension.getInvoker(arg0, arg1, arg2); }
} ```
- 简易流程图
- 分析
- ExtensionLoader的type为需要扩展的类,objectFactory为ExtensionFactory的扩展(源码得出为AdaptiveExtensionFactory)
- 顺序: 1.通过配置文件加载adaptive类(如果没有采用动态编程的方式) 2.通过adpative类去代理扩展类(从配置文件加载)
- 通过adpative类去代理扩展类: 1.通过URL获取key 2.通过key找到相应的扩展类
- @SPI、@Activate、@Adaptive注解分析
-
需要扩展的类加上@SPI注解
-
扩展的实现类加上@Activate注解
-
@Adaptive为标记实现一个适配器类,并且动态生成(通过代理生成)
EXTENSION_LOADERS 例如protocol和对应ExtensionLoader 1.ExtensionLoader(new创建) type 扩展接口名 objectFactory:ExtensionFactory的AdaptiveExtension --->AdaptiveExtensionFactory cachedAdaptiveInstance:存放代理类 1.代理类含有需要代理的类(扩展类) -->cachedClasses:存放扩展类(从配置文件获取) 1.1 需要扩展的类需要加上SPI注解,注解上的值为默认扩展 2.如果从配置文件没有加载代理类,需要单独创建 2.1 单独创建需要通过动态编程的方式实现 3.通过代理类加载扩展类 3.1 在EXTENSION_LOADERS中根据type查找ExtensionLoader 3.2 根据url中的name在cachedInstances(<String, Holder>)中查找实例(刚开始为空) 3.2.1 根据扩展类名在EXTENSION_INSTANCES中查找、 --->如果没有,则clazz.newInstance()后放入其中 3.2.2 遍历扩展类实例的set方法,对其实例属性进行注入 --->objectFactory.getExtension(pt, property)//根据ExtensionFactory的代理类获取待注入类 --->根据ExtensionFactory的扩展类去加载(没有则添加)
-
- 分析
-
自定义Bean的过程
-
动态编程
-
服务导出
registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=meetup-demo-provider&dubbo=2.0.2&pid=21160®istry=zookeeper&release=2.7.0×tamp=1553236781382
- 服务注册流程图
- Invoker
- 创建Wrapper(通过操作字节码生成Wrapper的子类)
ClassGenerator cc = ClassGenerator.newInstance(cl); cc.setClassName //类名 cc.setSuperClass //父类名 cc.addDefaultConstructor(); //默认无参构造 cc.addField("") //添加字段 cc.addMethod //添加方法 Class<?> wc = cc.toClass(); //转换为class类 wc.newInstance() //实例化
- 封装成Invoker
- Invoker.invoker最终调用 Wrapper.invokeMethod
- 创建Wrapper(通过操作字节码生成Wrapper的子类)
- 注册中心
- 服务注册流程图
-
- 引用时机
- Spring容器调用ReferenceBean的afterPropertiesSet引用服务(饿汉式)
- 在ReferenceBean对应的服务被注入到其他类中引用(懒汉式)
- 默认情况下,Dubbo使用懒汉式。如果需要饿汉式,通过配置dubbo:reference的init属性开启
- 引用入口
- ReferenceBean的getObject方法
- 当服务被注入其他类时,Spring会第一时间调用getObject方法
- 不管哪种引用,最后会得到一个Invoker实例,但并不能暴露给用户使用,通过代理工厂类ProxyFactory为服务接口生成代理类
- 当服务被注入其他类时,Spring会第一时间调用getObject方法
- Protocol的代理类生成Invoker
- RegistryProtocol 以及(1.QosProtocolWrapper 2.ProtocolFilterWrapper 3.ProtocolListenerWrapper)包装类
- 按照顺序层层包装RegistryProtocol,对外返回ProtocolListenerWrapper包装类(向内调用)
- 在QosProtocolWrapper包装时会启用qos服务(netty)
- RegistryProtocol 以及(1.QosProtocolWrapper 2.ProtocolFilterWrapper 3.ProtocolListenerWrapper)包装类
- ReferenceBean的getObject方法
- 引用时机
-
ServiceBean的源码分析
- 参考资料