博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
dubbo AdaptiveExtension
阅读量:7049 次
发布时间:2019-06-28

本文共 5326 字,大约阅读时间需要 17 分钟。

AdaptiveExtension
自适应Extension,作者其实在使用Extension方和Extension之间插入AdaptiveExtension用来自适应,也可以说是适配。
所以,我们发现,这里其实有三种,
1,一种是自动生成的Adaptive根据url参数来选择具体实现;
2,一种是自己实现一个Adaptive,写自己的逻辑选择具体实现,比如AdaptiveExtensionFactory,Compiler。这种都是在ExtensionLoader中需要使用,一般是不会这么做的。
3,还有一种没有Adaptive,实现一个adapter,比如TelnetHandler。这种因为不能根据url参数来决定使用哪一个实现。
从结构上看AdaptiveExtension是很重要的角色,我们配置了一些插件,但是具体使用哪一个如果用硬编码自然是不可能的,而这种自适应的方式得益于dubbo的状态数据信息都可以通过URL来获取,被叫做以URL为总线的模式。而自适应即是根据这些信息来决定调用哪一个插件的实现。
 
ExtensionLoader是插件机制的核心类:
private final Holder cachedAdaptiveInstance = new Holder();// 获得AdaptiveExtension入口public T getAdaptiveExtension() {        // cachedAdaptiveInstance缓存        Object instance = cachedAdaptiveInstance.get();        if (instance == null) {
// 缓存没有 // 判断创建时有没有报错过 if(createAdaptiveInstanceError == null) { // 这种是经典的同步写法,先取一下,没有的话,再锁住,然后再取一下,而不是直接锁。 synchronized (cachedAdaptiveInstance) { // 再取 instance = cachedAdaptiveInstance.get(); if (instance == null) { try { // 创建 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); } } return (T) instance; } private T createAdaptiveExtension() { try { return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e); } } private Class
getAdaptiveExtensionClass() { getExtensionClasses(); if (cachedAdaptiveClass != null) { return cachedAdaptiveClass; } // 依然没有cachedAdaptiveClass 说明没有配置@Adaptive 那就自动生成一个 return cachedAdaptiveClass = createAdaptiveExtensionClass(); } private Class
createAdaptiveExtensionClass() { // 组装java代码 String code = createAdaptiveExtensionClassCode(); ClassLoader classLoader = findClassLoader(); com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); // 编译出来 return compiler.compile(code, classLoader); } private Map
> getExtensionClasses() { Map
> classes = cachedClasses.get(); if (classes == null) { synchronized (cachedClasses) { classes = cachedClasses.get(); if (classes == null) { classes = loadExtensionClasses(); cachedClasses.set(classes); } } } return classes; } private Map
> loadExtensionClasses() { final SPI defaultAnnotation = type.getAnnotation(SPI.class); if(defaultAnnotation != null) { String value = defaultAnnotation.value(); if(value != null && (value = value.trim()).length() > 0) { String[] names = NAME_SEPARATOR.split(value); if(names.length > 1) { throw new IllegalStateException("more than 1 default extension name on extension " + type.getName() + ": " + Arrays.toString(names)); } if(names.length == 1) cachedDefaultName = names[0]; } } Map
> extensionClasses = new HashMap
>(); loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY); loadFile(extensionClasses, DUBBO_DIRECTORY); loadFile(extensionClasses, SERVICES_DIRECTORY); return extensionClasses; }

以下方法都会触发loadFile,这个方法就会读取文件,解析出各个插件的class。有@Adaptive注解的会放入赋值给cachedAdaptiveClass。

下面以Transporter接口为例进行说明自动生成的代码:

@SPI("netty")public interface Transporter {    @Adaptive({Constants.SERVER_KEY, Constants.TRANSPORTER_KEY})    Server bind(URL url, ChannelHandler handler) throws RemotingException;     @Adaptive({Constants.CLIENT_KEY, Constants.TRANSPORTER_KEY})    Client connect(URL url, ChannelHandler handler) throws RemotingException;}

动态生成类:

public class Transporter$Adaptive implements Transporter {     public Server bind(URL arg0, ChannelHandler arg1) throws RemotingException {        URL url = arg0;        String extName = url.getParameter("server",                url.getParameter("transporter", "netty"));        Transporter extension = (Transporter) ExtensionLoader                .getExtensionLoader(Transporter.class).getExtension(extName);        return extension.bind(arg0, arg1);    } }

 

Adaptive机制是一个很好的设计,很好的解决多方案实现的适配问题,如果你遇到类似的代码架构的时候,多想一下更加有扩展性的设计。

 

 

 

 

转载地址:http://qndol.baihongyu.com/

你可能感兴趣的文章
cherrypy安装使用,配置python环境变量
查看>>
MVC验证12-使用DataAnnotationsExtensions对整型、邮件、最小值、文件类型、Url地址等验证...
查看>>
Source not found
查看>>
【CLRS】《算法导论》读书笔记(一):堆排序(Heapsort)
查看>>
支持类型过滤的枚举器
查看>>
HDU 4275 Color the Tree(树同构)
查看>>
php里Array2xml
查看>>
以boost::function和boost:bind取代虚函数
查看>>
oracle监听器(listener)配置心得
查看>>
wince -- RS485半双工实现
查看>>
nginx 源码学习笔记(二)——nginx精粹-模块
查看>>
DirectX截图黑屏的解决办法
查看>>
Expanding Cat5e LAN segments over 100 metres using OUTREACH Ethernet LAN extenders
查看>>
关于Oracle冷备份与热备份的对比
查看>>
C#条件判断-嵌套if结构
查看>>
Selenium:Hello,World!
查看>>
HibernateTemplate 查询
查看>>
ListView控件的基本操作
查看>>
jQuery 参考手册 - 属性操作
查看>>
C–gcc命令行下的参数
查看>>