dubbo-spi(1)

2 篇文章 0 订阅
2 篇文章 0 订阅

为什么dubbo不直接用jdk的spi机制,而是自己模仿实现了一个spi机制呢?

jdk的spi会在一次实例化所有实现,可能会比较耗时,而且有些可能用不到的实现类也会实例化,浪费资源而且没有选择。另外dubbo的spi增加了对扩展点IOC和AOP的支持,一个扩展点可以直接setter注入其他扩展点。这是jdk spi不支持的。

dubbo的spi文件定义在META-INF/dubbo/internal/路径下面和jdk的spi类似。但是dubbo的spi文件里面格式和jdkSPI有点不一样,格式是扩展名=全路径的类名,比如

threadlocal=com.alibaba.dubbo.cache.support.threadlocal.ThreadLocalCacheFactory

lru=com.alibaba.dubbo.cache.support.lru.LruCacheFactory

jcache=com.alibaba.dubbo.cache.support.jcache.JCacheFactory

扩展名的作用是用来实现选择性的加载实现类。

dubbo的spi使用ExtensionLoader来实现。

//这个方法用户获取一个接口的ExtensionLoader
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
    if (type == null)
        throw new IllegalArgumentException("Extension type == null");
    if(!type.isInterface()) {
throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");
} if(!withExtensionAnnotation(type)) { throw new IllegalArgumentException("Extension type(" + type + ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!"); } //从map从获取 ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); if (loader == null) { //map中没有的时候会创建并缓存到map里面 EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); } return loader; }
 //这个方法通过扩展名获取一个实现类
public T getExtension(String name) {
   if (name == null || name.length() == 0)
       throw new IllegalArgumentException("Extension name == null");
   if ("true".equals(name)) {
       return getDefaultExtension();
   }
   Holder<Object> holder = cachedInstances.get(name);
   if (holder == null) {
       //创建一个holder放到map里面 putIfAbsent保证了只有一个能放进去
       cachedInstances.putIfAbsent(name, new Holder<Object>());
       holder = cachedInstances.get(name);
   }
   Object instance = holder.get();
   //双重判空加锁 创建一个单例的实现类对象
   if (instance == null) {
       synchronized (holder) {
            instance = holder.get();
            if (instance == null) {
                instance = createExtension(name);
                holder.set(instance);
            }
        }
   }
   return (T) instance;
}
private ExtensionLoader(Class<?> type) {
    this.type = type;
    //objectFactory的作用是为dubbo的IOC提供对象
    objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}


//获取一个扩展装饰类的对象 如果类没有用Adaptive注解就动态创建一个装饰类
public T getAdaptiveExtension() {
    //优先从缓存获取
    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;
}
--------------------- 
作者:xujiajun955 
来源:CSDN 
原文:https://blog.csdn.net/xujiajun1994/article/details/80926323 
版权声明:本文为博主原创文章,转载请附上博文链接!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值