彩色科技|Dubbo自适应扩展机制( 二 )
- 根据传入的类型从classpath中查找META-INF/dubbo/internal和META-INF/dubbo路径下所有对应的扩展点配置文件
- 读取扩展点配置文件中所有的键值对
- 根据键值对缓存Class对象 , 如果类有同类型参数的构造函数 , 则为包装类 , 会缓存在另一个容器中
- 实例化对象 , 缓存后并返回
if (CollectionUtils.isNotEmpty(wrapperClasses)) {// 循环创建 Wrapper 实例for (Class> wrapperClass : wrapperClasses) {// 将当前 instance 作为参数传给 Wrapper 的构造方法 , 并通过反射创建 Wrapper 实例 。// 然后向 Wrapper 实例中注入依赖 , 最后将 Wrapper 实例再次赋值给 instance 变量instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));}}
其实就是使用静态代理来实现AOP2.2 扩展点自动装配返回实例前会遍历所有的setXXX方法 , 判断set方法参数是否存在自适应对象 , 如果存在则通过ExtensionLoader加载自适应对象然后进行赋值 , 可以通过方法上加org.apache.dubbo.common.extension.DisableInject注解来屏蔽该功能 。 该功能其实就是实现了IOC , 具体可以看ExtensionLoader的injectExtension方法 。
2.3 扩展点自适应同上面介绍的一样 , Dubbo的SPI可以根据传入的URL参数中携带的数据来动态选择具体的实现 。
2.4 扩展点自动激活上面介绍过 , Adaptive注解是加在方法上的 , 类似的有个注解org.apache.dubbo.common.extension.Activate是加在实现类上 。 当加在Class上时 , ExtensionLoader会将对应的key和Class信息缓存到另一个容器中 , 后续可以通过ExtensionLoader获取某一类的实现列表 , 既如下方法
public List getActivateExtension(URL url, String[] values){...}
3. ExtensionLoader自适应扩展机制ExtensionLoader自适应扩展机制的大概实现逻辑是这样的:Dubbo会为拓展接口生成具有代理功能的代码 , 然后通过 javassist 或 jdk 编译这段代码 , 得到 Class 类 。 最后再通过反射创建代理类 , 在代理类中 , 就可以通过URL对象的参数来确定到底调用哪个实现类 。 主要实现在createAdaptiveExtensionClass方法中 。private Class> createAdaptiveExtensionClass() {String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();ClassLoader classLoader = findClassLoader();org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();return compiler.compile(code, classLoader);}
上面的Protocol接口经过处理后的内容如下:public class Protocol$Adaptive implements org.apache.dubbo.rpc.Protocol {public void destroy() {throw new UnsupportedOperationException("The method public abstract void org.apache.dubbo.rpc.Protocol.destroy() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");}public int getDefaultPort() {throw new UnsupportedOperationException("The method public abstract int org.apache.dubbo.rpc.Protocol.getDefaultPort() of interface org.apache.dubbo.rpc.Protocol is not adaptive method!");}public org.apache.dubbo.rpc.Exporter export(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {if (arg0 == null) {throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");}if (arg0.getUrl() == null) {throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");}org.apache.dubbo.common.URL url = arg0.getUrl();String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());if (extName == null) {throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");}org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);return extension.export(arg0);}public org.apache.dubbo.rpc.Invoker refer(java.lang.Class arg0, org.apache.dubbo.common.URL arg1) throws org.apache.dubbo.rpc.RpcException {if (arg1 == null) {throw new IllegalArgumentException("url == null");}org.apache.dubbo.common.URL url = arg1;String extName = (url.getProtocol() == null ? "dubbo" : url.getProtocol());if (extName == null) {throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.Protocol) name from url (" + url.toString() + ") use keys([protocol])");}org.apache.dubbo.rpc.Protocol extension = (org.apache.dubbo.rpc.Protocol) ExtensionLoader.getExtensionLoader(org.apache.dubbo.rpc.Protocol.class).getExtension(extName);return extension.refer(arg0, arg1);}}
- 所持股份|万兴科技:公司控股股东、实际控制人吴太兵质押150万股
- 发布公告|数量过半!博创科技:天通股份累计减持约150万股
- 英雄科技聊数码|蔡崇信有实力买下篮网,那身价3200亿的马云,能买下几支NBA球队
- 科技前沿阵地|涨疯了!海思安防芯片遭哄抬“围剿”
- 月影浓|吴亦凡机械造型走秀 垫肩披风搭银框眼镜科技感足
- 中国历史发展过程|中国历史发展过程.中国的科技史界过去半个多世纪
- 天津|桂发祥:不再持有昆汀科技股份
- 消费|减持!天通股份:减持博创科技约32万股
- 处罚|老周侃股:吉鑫科技大股东应补偿踩雷投资者
- 华中科技大学|杯具!超本科线95分,本科有路不走,却梦幻般碰瓷,撞开专科的门