zoukankan      html  css  js  c++  java
  • Dubbo SPI 源码深入分析

    1.先看入口在哪里,我们加载自定义的扩展都会写这行代码,那么就从分析ExtensionLoader开始了

    ExtensionLoader.getExtensionLoader(XXX.class).getExtension("diyExtension");

    1.1 getExtensionLoader
     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 an interface!");
            }
            if (!withExtensionAnnotation(type)) {
                throw new IllegalArgumentException("Extension type (" + type +
                        ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
            }
         // 缓存思想大量应用,先看这个ExtensionLoader是否创建过了,创建过的会放在chm里面
            ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
            if (loader == null) {
            //没创建过就创建,放到chm里面 EXTENSION_LOADERS.putIfAbsent(type,
    new ExtensionLoader<T>(type)); loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); } return loader; }

    1.1.1 new ExtensionLoader 的时候,先判断你是不是在要ExtensionFactory的扩展点,如果不是的话,就去拿ExtensionFactory的自适应扩展点(这里有待进一步研究为何这个逻辑)然后赋值给objectFactory (ExtensionLoader(protocol) 的成员变量:private final ExtensionFactory objectFactory;)

    private ExtensionLoader(Class<?> type) {
            this.type = type;
            objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class)
            .getAdaptiveExtension()); }

    1.1.2

    此时回到上层方法,我们走完了new ExtensionLoader得到了一个ExtensionLoader,这个ExtensionLoader里面,带着成员变量ExtensionFactory,其值是经过自适应处理的ExtensionFactory,然后把 这个ExtensionLoader放到了chm里面(为什么呢?比如我在1.1处ExtensionLoader.getExtensionLoader(XXX.class)的XXX处入参传的是Protocol入参,但是你给我的是ExtensionFactory 相关的扩展点,是不是我要个苹果 ,看起来你给了我香蕉?)

     ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
            if (loader == null) {
                EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
                loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
            }

    1.2 此时执行1.1处的 getExtension,这里,是根据传的我们自定义的名字,去一个chm找是否有,没有创建一个,放到chm里,再查出来把他返回

     public T getExtension(String name) {
            if (StringUtils.isEmpty(name)) {
                throw new IllegalArgumentException("Extension name == null");
            }
            if ("true".equals(name)) {
                return getDefaultExtension();
            }
            Holder<Object> holder = getOrCreateHolder(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 Holder<Object> getOrCreateHolder(String name) {
      
      //ExtensionLoader的成员变量 private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<>();
        Holder<Object> holder = cachedInstances.get(name);
    if (holder == null) {
    cachedInstances.putIfAbsent(name, new Holder<>());
    holder = cachedInstances.get(name);
    }
    return holder;
    }
     
    public class Holder<T> {

    private volatile T value;

    public void set(T value) {
    this.value = value;
    }

    public T get() {
    return value;
    }

    }
     
    
    
  • 相关阅读:
    你是怎么把字符串“2016-11-16” 变为 “16/11/2016” 的?
    js-------》(小效果)实现倒计时及时间对象
    Ruby方法
    JAVASCRIPT事件详解-------原生事件基础....
    html5的小知识点小集合
    原生js实现的效果
    IDEA 实用功能Auto Import:自动优化导包(自动删除、导入包)
    8.SpringBoot 模板引擎 Thymeleaf
    7.SpringBoot 之 Web
    6.日志的使用
  • 原文地址:https://www.cnblogs.com/andydlz/p/13324453.html
Copyright © 2011-2022 走看看