码迷,mamicode.com
首页 > 其他好文 > 详细

Dubbo SPI

时间:2017-11-13 16:35:20      阅读:229      评论:0      收藏:0      [点我收藏+]

标签:inter   names   exp   工厂   rpc   list   listen   nload   col   

Dubbo SPI是Dubbo留的扩展点

例如Dubbo的 Protocol 。 ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension()

Dubbo SPI 加载文件

  loadFile(extensionClasses, "META-INF/dubbo/internal/");
  loadFile(extensionClasses, "META-INF/dubbo/");
  loadFile(extensionClasses, "META-INF/services/");

 

Dubbo SPI:(核心类 ExtensionLoader )
【加载SPI文件】
它是按文件去加载的,每个类都有自己的 ExtensionLoader ,保存了相应的SPI文件里面的信息:
[1]. 类上有 @Adaptive 放在 cachedAdaptiveClass 中
[2]. 类中存在只有一个参数的构造函数,且参数就是这个类本身,则放在 cachedWrapperClasses 中
[3].
类上有 @Activate,将 @Activate 放在 cachedActivates<String:NAME, Activate> 中
将类放在 cachedNames<Class, String:NAME> 和 cachedClasses<String:NAME, Class> 中

 

举例,如:META-INF\dubbo\internal\com.alibaba.dubbo.rpc.ProxyFactory
NAME | Class
stub=com.alibaba.dubbo.rpc.proxy.wrapper.StubProxyFactoryWrapper
jdk=com.alibaba.dubbo.rpc.proxy.jdk.JdkProxyFactory
javassist=com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory

StubProxyFactoryWrapper 上没有注解,但是有一个参数的构造函数,且参数为 ProxyFactory ,故在 ProxyFactory 相应的 ExtensionLoader 中,cachedWrapperClasses 存放了 StubProxyFactoryWrapper
JdkProxyFactory 上没有注释,只有默认的构造函数,所以走分支[3],将 JdkProxyFactory 放在 cachedNames<Class=JdkProxyFactory, String:NAME=jdk> 和 cachedClasses<String:NAME=jdk, class="JdkProxyFactory"> 中
JavassistProxyFactory 上没有注释,只有默认的构造函数,所以走分支[3],将 JdkProxyFactory 放在 cachedNames<Class=JavassistProxyFactory, String:NAME=javassist> 和 cachedClasses<String:NAME=javassist, class="JavassistProxyFactory"> 中

举例,如:META-INF\dubbo\internal\com.alibaba.dubbo.common.extension.ExtensionFactory
NAME | Class
adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory

AdaptiveExtensionFactory 上有 @Adaptive ,放在 cachedAdaptiveClass 中。(它是一个适配工厂类)
SpiExtensionFactory 不满足[1]、[2],也没有 @Activate ,放在 cachedNames<Class, String:spi> 和 cachedClasses<String:spi, Class> 中
SpringExtensionFactory 不满足[1]、[2],也没有 @Activate ,放在 cachedNames<Class, String:spring> 和 cachedClasses<String:spring, Class> 中
附:
AdaptiveExtensionFactory 是一个适配工厂类,通过它可以去找到 spi,spring 对应的 ExtensionFactory

 

ExtensionLoader.getExtensionLoader(X).getAdaptiveExtension():获取 X 适配的扩展(X如:Protocol,ProxyFactory)
1. 如果存在 cachedAdaptiveClass ,就返回 cachedAdaptiveClass。(一般是一个适配工厂类)
2. 否则通过 javassist 动态生成一个代理类,然后赋值给 cachedAdaptiveClass 返回
动态生成的这个代理类,会重写 X 中带有 @Adaptive 的方法,其他的方法默认抛出异常
重写的方法中通常都会通过 ExtensionLoader.getExtensionLoader(X).getExtension(extName) 来获取相应的扩展实现
综上,getAdaptiveExtension() 就是获取适配器。适配器作用:获取与 X 适配的扩展

ExtensionLoader.getExtensionLoader(X).getExtension(extName):根据扩展名 extName 获取 X 对应的扩展实现
1. 从 cachedClasses 中获取扩展的实现类,并 clazz.newInstance()
2. 利用装饰模式,将 cachedWrapperClasses 包裹在 instance 上

 

Q&A:
1. Dubbo 的 Filter 是什么时候生效的?
在 com.alibaba.dubbo.rpc.Protocol 的 SPI 文件中,有一个 filter=com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper。
那么 Dubbo 在服务暴露 or 引用时,会去先调用 ProtocolFilterWrapper.export(Invoker),这个时候就会将适配的 Filter 装饰在 Invoker 上

2. Dubbo 服务暴露时,何时做的服务注册?
ServiceConfig.doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) 会去做服务注册。
protocol.export(invoker) --> RegisteryProtocol.export() --> DubboProtocol.export()
之所以服务注册时,会去调用 DubboProtocol.export(),这归功于 listener=com.alibaba.dubbo.rpc.protocol.ProtocolListenerWrapper。
ProtocolListenerWrapper 会调用 DubboProtocol.export()

Dubbo SPI

标签:inter   names   exp   工厂   rpc   list   listen   nload   col   

原文地址:http://www.cnblogs.com/kevin-yuan/p/7826277.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!