1-dubbo源码分析之扩展机制

2018-08-30  本文已影响0人  致虑

一.概览

整体描述

二.扩展点加载流程

1-获取ExtensionLoader
    @Test
    public void testAdaptiveExtension() throws Exception {
        SimpleExt ext = ExtensionLoader.getExtensionLoader(SimpleExt.class).getAdaptiveExtension();

        Map<String, String> map = new HashMap<String, String>();
        map.put("key", "impl_wxshi");
        URL url = new URL("p1", "1.2.3.4", 1010, "path", map);

        String echo = ext.yell(url, "haha");
        assertEquals("xxxxx", echo);
    }
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!");
       }
       /**
        * 这个类型必须加上SPI注解,否则报错
        */
       if (!withExtensionAnnotation(type)) {
           throw new IllegalArgumentException("Extension type(" + type + ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");
       }

       /**
        * 从缓存中获取
        */
       ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
       if (loader == null) {
           /**
            * 取不到创建一个放入EXTENSION_LOADERS中
            */
           EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
           loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
       }
       return loader;
   }
/**
 * ExtensionFactory自身也是个扩展点,它被SPI注解
 * 它有3个provider,分别是adaptive,spi和spring
 * ExtensionFactory是主要是用来加载被注入的类的实现,分为SpiExtensionFactory和SpringExtensionFactory两个,分别用来加载SPI扩展实现和Spring中bean的实现。
 */
@SPI
public interface ExtensionFactory {

    /**
     * Get extension.
     *
     * 获取指定类型的指定名称的扩展点
     *
     * @param type object type.
     * @param name object name.
     * @return object instance.
     */
    @Adaptive
    <T> T getExtension(Class<T> type, String name);
 }
/**
 * AdaptiveExtensionFactory
 * AdaptiveExtesnionFactory是dubbo自定义的adaptive,由于聚合了SpringExtensionFactory和SpiExtensionFactory,从而能对需要注入的对象的所有set方法进行注入
 */
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {

    private final List<ExtensionFactory> factories;

    public AdaptiveExtensionFactory() {
        ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
        List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
        for (String name : loader.getSupportedExtensions()) {
            list.add(loader.getExtension(name));
        }
        factories = Collections.unmodifiableList(list);
    }

    @Override
    public <T> T getExtension(Class<T> type, String name) {
        for (ExtensionFactory factory : factories) {
            T extension = factory.getExtension(type, name);
            if (extension != null) {
                return extension;
            }
        }
        return null;
    }
}

看见@SPI了,同时重点关注下 @Adaptive注解就明确了,这个注解在上面讲了,如果在类上,优先级最高,那取得自适应点就是这个AdaptiveExtensionFactory了,干的事情看后面的作用就知道了,获取扩展点的流程我们用自己的接口解释,这里基本都是一致的,继续往后划重点。


2-自定义扩展点加载

无非就是解析配置项,获取扩展点类路径,通过类加载器加载,继续

 private Class<?> getAdaptiveExtensionClass() {
     /**
      * 触发SPI流程的扫描
      */
     getExtensionClasses();

     /**
      * 如果通过上面的步骤可以获取到cachedAdaptiveClass直接返回,如果不行的话,就得考虑自己进行利用动态代理创建一个了
      * 什么情况下不为空?当扩展类上打上@Adaptive注解的时候,就会将这个类直接返回。如果没有上注解,怎么办,就得自己生成了,也就是createAdaptiveExtensionClass
      */
     if (cachedAdaptiveClass != null) {
         return cachedAdaptiveClass;
     }

     /**
      * 利用动态代理创建一个扩展类
      * 如果用户没有声明adaptive(cachedAdaptiveClass为空)则dubbo自动生成一个adaptive
      */
     return cachedAdaptiveClass = createAdaptiveExtensionClass();
 }
往下走就会发现,如果cachedAdaptiveClass != null,直接返回,这个就是体现优先级的地方了。若没有,继续深入createAdaptiveExtensionClass()

code还是字符串形式,那后面的代码就清楚了


3.执行具体的方法

看到执行逻辑如下:
- 1.获取扩展点的Extensionloader,之前的流程中已经缓存了,所以直接获取
- 2.调用getExtension(extName)方法获取具体的扩展点,这个就是最后获取真正代理的时候了

上一篇 下一篇

猜你喜欢

热点阅读