02 dubbo源码学习_SPI

1. dubbo为什么需要SPI

dubbo的SPI作用主要是扩展性,当一个接口存在多种实现,如何在代码运行过程中,根据不同的参数选择不同的实现;
java中也提供了SPI,只是它的SPI过于简单:

  1. 一次性全部加载所有实现,无法做到懒加载;
  2. java的SPI无法实现控制反转,对于实现如果有依赖其他类,无法自动注入;

所以在dubbo中引入了自定义的SPI组件;

2. dubbo的SPI源码分析

dubbo的SPI主要包括四个方法:

  • ExtensionLoader.getExtensionLoader(Class);
  • ExtensionLoader.getExtensionLoader(SimpleExt.class).getAdaptiveExtension();
  • ExtensionLoader.getExtensionLoader(SimpleExt.class).getExtension(String);
  • ExtensionLoader.getExtensionLoader(SimpleExt.class).getDefaultExtension();

后面三个方法是获取具体的实现,第一个是获取一个加载器,我们先从第一个看起:

2.1 getExtensionLoader

2.1. 源码分析

源码分析,我们先从这里开始吧:

@Test
public void test_Debug_GetExtension_Process() throws Exception {
        final ExtensionLoader<SimpleExt> extensionLoader = ExtensionLoader.getExtensionLoader(SimpleExt.class);
        System.out.println(extensionLoader);
}

1. ExtensionLoader#getExtensionLoader(Class type)

public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
        // 如果为空,报错
        if (type == null)
            throw new IllegalArgumentException("Extension type == null");
        // 如果不是接口,报错,因为SPI是针对接口的扩展
        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) {
            // 创建一个ExtensionLoader,并添加到缓存中;
            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
            loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
        }
        return loader;
}

2.ExtensionLoader#ExtensionLoader构造器

private ExtensionLoader(Class<?> type) {
        this.type = type;
        // 我们传入的是SimpleExt.class,所以会执行else;
        objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}

ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()这段代码,getAdaptiveExtension()之前跟我们前面分析的是一样的,因为type==ExtensionFactory.class,所以ExtensionFactory的ExtensionLoader的objectFactory属性为null;

到这里先总结一下:

  1. 获取一个接口的扩展实现时,首先通过ExtensionLoader.getExtensionLoader(Class)获取一个ExtensionLoader加载器,每个SPI接口都有一个自己的ExtensionLoader(创建时放入缓存);
  2. 而ExtensionLoader是通过ExtensionFactory来加载的,ExtensionFactory也是一个SPI,它有两个实现:
    • SpiExtensionFactory
    • SpringExtensionFactory
    • AdaptiveExtensionFactory
  3. ExtensionLoader.getExtensionLoader(ExtensionFactory.class)只会实例化一次,在之后有别的SPI接口创建时,不会再对它初始化,因为它已经初始化过了;

就是在加载一个实现时,是从Dubbo的SPI中加载还是Spring容器中加载;

3.SpiExtensionFactory与SpringExtensionFactory
前者是在dubbo的SPI体系(ExtensionLoader)中获取对象
后者是在SpringApplicationContext中获取对象;
在dubbo的IOC功能中injectExtension,注入依赖的对象是从哪个体系中查找;

2.2 getAdaptiveExtension

2.2.1 源码分析

源码接着上面的:ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()中的getAdaptiveExtension()来说,在分析它之前,得先说明什么是AdaptiveExtension;

对于Dubbo的SPI接口如果没有编码实现一个@Adaptive的实现类的话,Dubbo会自动为接口生成一个实现类;

  • @Adaptive:如果加在实现类上的话,那么getAdaptiveExtension则返回该实现类;并且一个SPI接口只允许有一个Adaptive实现类;
    在这里插入图片描述
  • @Adaptive:如果加在接口方法上的话,那么Dubbo会生成一个实现类,会代理@Adaptive接口方法;
    在这里插入图片描述

Adaptive实现类 ExtensionLoader#getAdaptiveExtension()

public T getAdaptiveExtension() {
        // 从缓存中获取实例,从这里也可以看出,一个SPI接口只允许有一个Adative实现类;
        Object instance = cachedAdaptiveInstance.get();
        if (instance == null) {
            if (createAdaptiveInstanceError == null) {
                synchronized (cachedAdaptiveInstance) {
                    // 这里做了个双重检查,加锁之后再次对它进行判断;
                    instance = cachedAdaptiveInstance.get();
                    if (instance == null) {
                        try {
                                // 创建Adaptive实例
                                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;
}

核心逻辑是在createAdaptiveExtension方法内:

private T createAdaptiveExtension() {
        try {
                // getAdaptiveExtensionClass 返回一个Class类型,之后调用该Class的newInstance生成实例;
                // 而inject就是dubbo的IOC功能,它能实现对SPI接口中所依赖的对象进行注入;
                return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
                throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
        }
}

接着先来看 getAdaptiveExtensionClass,且SPI有默认实现的Adaptive实现类的情况:

缓存名称含义
cachedDefaultName接口SPI的Value,如果SPI(“A”)表示当前接口的Default实现是A
cachedAdaptiveClass接口SPI的编码方式Adaptive实现类的clazz引用
cachedWrapperClassesSet SPI接口的实现类构造方法中包含当前SPI类型的Set集合,AOP功能
cachedActivatesMap SPI实现类如果不满足cachedAdaptiveClass的情况下,会将key和activate注解存到这里
cachedNamesMap SPI实现类中非Adaptive实现类的实现,key=实现类clazz,value=实现类名称
extensionClassesMap 作用与cachedNames一样,只是它的key=实现类名称,value=实现类clazz
cachedInstancesMap 作用是存放非Adaptive实现的实例对象,key=name,value=Holder
EXTENSION_INSTANCESMap 作用是存放非Adaptive实现的实例对象,key=clazz,value=实例对象
private Class<?> getAdaptiveExtensionClass() {
        // 加载当前SPI接口的实现类
        getExtensionClasses();
        // cachedAdaptiveClass = SPI的编码方式Adaptive实现类的clazz引用  
        if (cachedAdaptiveClass != null) {
            return cachedAdaptiveClass;
        }
        // 如果当前SPI接口没有编码方式实现的Adaptive,则下面进行生成一个;
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
}

private Map<String, Class<?>> getExtensionClasses() {
        // 首先从缓存中获取,如果没有,则通过loadExtensionClasses进行加载
        Map<String, Class<?>> classes = cachedClasses.get();
        if (classes == null) {
            synchronized (cachedClasses) {
                classes = cachedClasses.get();
                // 这里做了个双重检查判断;
                if (classes == null) {
                    classes = loadExtensionClasses();
                    cachedClasses.set(classes);
                }
            }
        }
        return classes;
}


private Map<String, Class<?>> loadExtensionClasses() {
        // 获取当前接口ExtensionFactory的SPI注解
        final SPI defaultAnnotation = type.getAnnotation(SPI.class);
        if (defaultAnnotation != null) {
            // 如果该注解的value为值,并且包含,号,则解析报错:more than 1 default extension name on extension
            String value = defaultAnnotation.value();
            if ((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));
                }
                // cachedDefaultName=SPI注解中的value
                if (names.length == 1) cachedDefaultName = names[0];
            }
        }

        Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
        loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
        loadDirectory(extensionClasses, DUBBO_DIRECTORY);
        loadDirectory(extensionClasses, SERVICES_DIRECTORY);
        return extensionClasses;
}

private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir) {
        // META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory
        // adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
        // spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory

        // 这个路径里面存放的是SPI的实现类有哪些
        // 这里并不是一次加载所有的SPI,而是只加载当前ExtensionFactory的SPI实现;
        String fileName = dir + type.getName();
        try {
            Enumeration<java.net.URL> urls;
            // 获取 ExtensionLoader.class.getClassLoader()
            // 这个一般是指的应用类加载器 AppClassLoader;
            ClassLoader classLoader = findClassLoader();
            if (classLoader != null) {
                // 加载资源
                urls = classLoader.getResources(fileName);
            } else {
                urls = ClassLoader.getSystemResources(fileName);
            }
            if (urls != null) {
                while (urls.hasMoreElements()) {
                    // 通过classLoader.getResources得到的路径为:
                    // file:/xxx/dubbo/dubbo-common/target/classes/META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory
                    java.net.URL resourceURL = urls.nextElement();
                    // 加载资源
                    loadResource(extensionClasses, classLoader, resourceURL);
                }
            }
        } catch (Throwable t) {
            logger.error("Exception when load extension class(interface: " +
                    type + ", description file: " + fileName + ").", t);
        }
}


private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), "utf-8"));
            try {
                String line;
                // 每次读一行
                while ((line = reader.readLine()) != null) {
                    // 如果文件行内包含有#号,则先将其排除掉;
                    final int ci = line.indexOf('#');
                    if (ci >= 0) line = line.substring(0, ci);
                    line = line.trim();
                    if (line.length() > 0) {
                        try {
                            String name = null;
                            // 通过=号截取出key和value,name表示是key,line表示的是value
                            int i = line.indexOf('=');
                            if (i > 0) {
                                name = line.substring(0, i).trim();
                                line = line.substring(i + 1).trim();
                            }
                            if (line.length() > 0) {
                                // 先将 Class.forName(line, true, classLoader),将读到的实现类路径字符串转换Class类型;
                                // 加载Class;
                                loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
                            }
                        } catch (Throwable t) {
                            IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
                            exceptions.put(line, e);
                        }
                    }
                }
            } finally {
                reader.close();
            }
        } catch (Throwable t) {
            logger.error("Exception when load extension class(interface: " +
                    type + ", class file: " + resourceURL + ") in " + resourceURL, t);
        }
}


private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) throws NoSuchMethodException {
        // 判断clazz是否是type的子类;
        // interface com.alibaba.dubbo.common.extension.ExtensionFactory是class com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory的父类
        if (!type.isAssignableFrom(clazz)) {
            throw new IllegalStateException("Error when load extension class(interface: " +
                    type + ", class line: " + clazz.getName() + "), class "
                    + clazz.getName() + "is not subtype of interface.");
        }
        // ExtensionFactory的第一个实现类为AdaptiveExtensionFactory,而它的类上是有Adaptive注解的;
        if (clazz.isAnnotationPresent(Adaptive.class)) {
            // 如果包含,则将cachedAdaptiveClass设置为当前SPI接口的Adaptive实现类
            if (cachedAdaptiveClass == null) {
                cachedAdaptiveClass = clazz;
            } else if (!cachedAdaptiveClass.equals(clazz)) {
                throw new IllegalStateException("More than 1 adaptive class found: "
                        + cachedAdaptiveClass.getClass().getName()
                        + ", " + clazz.getClass().getName());
            }
        } 
        // 判断当前Adaptive实现类是否存在 当前SPI接口 ExtensionFactory的构造方法,如果有,则返回true;它的作用是做类似AOP,动态代理;在getExtension方法分析时会讲;
        else if (isWrapperClass(clazz)) {
            Set<Class<?>> wrappers = cachedWrapperClasses;
            if (wrappers == null) {
                cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
                wrappers = cachedWrapperClasses;
            }
            wrappers.add(clazz);
        } else {
            // 获取一下它的无参构造器,如果没有,这里会报错,错误信息会传至上一层;
            // 这也就是说,普通的SPI接口实现类,得提供无参构造器;
            clazz.getConstructor();
            // 如果SPI的文件中,配置的name为空,则会在这里生成一个;
            if (name == null || name.length() == 0) {
                name = findAnnotationName(clazz);
                if (name.length() == 0) {
                    throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL);
                }
            }
            // 从这里可以看出,一个SPI的实现在文件中可以配置多个name,用,号分隔即可;
            String[] names = NAME_SEPARATOR.split(name);
            if (names != null && names.length > 0) {
                // 如果当前clazz包含Adaptive注解,但如果包含这个Adaptive会走第一个if,没太清楚为什么这里做这个判断???
                Activate activate = clazz.getAnnotation(Activate.class);
                if (activate != null) {
                    cachedActivates.put(names[0], activate);
                }
                // 将clazz和定义的key放到cachedNames和extensionClasses
                // 做到通过key可找value,通过value可找key;
                for (String n : names) {
                    if (!cachedNames.containsKey(clazz)) {
                        cachedNames.put(clazz, n);
                    }
                    Class<?> c = extensionClasses.get(n);
                    if (c == null) {
                        extensionClasses.put(n, clazz);
                    } else if (c != clazz) {
                        throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName());
                    }
                }
            }
        }
}

SPI没有默认的Adaptive实现类的情况:
我们从getAdaptiveExtensionClass中的createAdaptiveExtensionClass开始看起;

private Class<?> createAdaptiveExtensionClass() {
        // 生成动态Adaptive的代码
        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);
}

上面代码首先是拼装class内容,然后动态编译生成Class文件;动态生成的类文件如下:

@SPI("impl1")
public interface SimpleExt {
    // @Adaptive example, do not specify a explicit key.
    @Adaptive
    String echo(URL url, String s);

    @Adaptive({"key1", "key2"})
    String yell(URL url, String s);

    // no @Adaptive
    String bang(URL url, int i);
}


public class SimpleExt$Adaptive implements com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt {
    public java.lang.String bang(com.alibaba.dubbo.common.URL arg0, int arg1) {
        throw new UnsupportedOperationException("method public abstract java.lang.String com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt.bang(com.alibaba.dubbo.common.URL,int) of interface com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt is not adaptive method!");
    }

    public java.lang.String echo(com.alibaba.dubbo.common.URL arg0, java.lang.String arg1) {
        if (arg0 == null) throw new IllegalArgumentException("url == null");
        com.alibaba.dubbo.common.URL url = arg0;
        String extName = url.getParameter("simple.ext", "impl1");
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) name from url(" + url.toString() + ") use keys([simple.ext])");
        com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt extension = (com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt.class).getExtension(extName);
        return extension.echo(arg0, arg1);
    }

    public java.lang.String yell(com.alibaba.dubbo.common.URL arg0, java.lang.String arg1) {
        if (arg0 == null) throw new IllegalArgumentException("url == null");
        com.alibaba.dubbo.common.URL url = arg0;
        String extName = url.getParameter("key1", url.getParameter("key2", "impl1"));
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) name from url(" + url.toString() + ") use keys([key1, key2])");
        com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt extension = (com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt.class).getExtension(extName);
        return extension.yell(arg0, arg1);
    }
}

比如上面的接口可以看到,生成的动态适配类只会重写接口中有@Adaptive注解的抽象方法,没有该注解的只是重写但方法体会抛异常;

再来看一看它所生成的动态适配类中的方法做了什么事;主要的是以下两行代码:

// 在运行时,可根据参数获取对应的SPI实现类
com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt extension = 
             (com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt.class).getExtension(extName);
// 然后调用它的方法;
extension.echo(arg0, arg1);

dubbo为什么要生成这个动态适配类Adaptive呢?
如果没有这个动态适配类,那我们该如何通过不同的参数寻找一个具体的SPI接口的实现类呢?而有了生成的这个适配类,可以通过它,做一些条件的解析,查询出具体的实现类,通过调适配类的方式完成对最终实现类的调用;

URL的使用

public java.lang.String echo(com.alibaba.dubbo.common.URL arg0, java.lang.String arg1) {
        if (arg0 == null) throw new IllegalArgumentException("url == null");
        com.alibaba.dubbo.common.URL url = arg0;
        String extName = url.getParameter("simple.ext", "impl1");
        if (extName == null)
            throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) name from url(" + url.toString() + ") use keys([simple.ext])");
        com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt extension = (com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt) ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.extensionloader.ext1.SimpleExt.class).getExtension(extName);
        return extension.echo(arg0, arg1);
    }

观察它的URL匹配原则,它会从URL中获取simple.ext参数,如果未设置,则默认使用impl1,是因为SimpleExt的SPI(“impl1”)的默认值是它;

2.3 injectExtension

位置:com.alibaba.dubbo.common.extension.ExtensionLoader#injectExtension
它的作用类似于Spring的IOC,开篇我说了java的SPI是不支持IOC的;

private T injectExtension(T instance) {
        try {
            if (objectFactory != null) {
                for (Method method : instance.getClass().getMethods()) {
                    // 如果有set开头的方法
                    if (method.getName().startsWith("set")
                            && method.getParameterTypes().length == 1
                            && Modifier.isPublic(method.getModifiers())) {
                        /**
                         * Check {@link DisableInject} to see if we need auto injection for this property
                         */
                        // 并且未禁用dubbo的IOC功能
                        if (method.getAnnotation(DisableInject.class) != null) {
                            continue;
                        }
                        Class<?> pt = method.getParameterTypes()[0];
                        try {
                            // 比如setExt(Ext2),这里得到的结果:ext2
                            String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
                            // 然后拿 com.alibaba.dubbo.common.extensionloader.ext2.Ext2去AdaptiveExtensionFactory中查找,如果存在,则给set方法赋值;
                            Object object = objectFactory.getExtension(pt, property);
                            if (object != null) {
                                method.invoke(instance, object);
                            }
                        } catch (Exception e) {
                            logger.error("fail to inject via method " + method.getName()
                                    + " of interface " + type.getName() + ": " + e.getMessage(), e);
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return instance;
}

2.4 getExtension

在getExtension之前,前面对非Adaptive实现类获取的都是Clazz对象,而getExtension是真正的初始化这些对象;

public T getExtension(String name) {
        // 首先进行参数校验
        if (name == null || name.length() == 0)
            throw new IllegalArgumentException("Extension name == null");
        // 如果传的name="true",则使用默认的实现类;其实就是cachedDefaultName所指的name,SPI("A")中的A值;
        if ("true".equals(name)) {
            return getDefaultExtension();
        }
        // cachedInstances是存放非Adaptive实现的实例对象,这里会将对象封装成一个Holder;
        // 在获取时,任然是先查缓存,如果没有,则去实例化;
        Holder<Object> holder = cachedInstances.get(name);
        if (holder == null) {
            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 T createExtension(String name) {
        // 通过name获取对应的Clazz对象
        Class<?> clazz = getExtensionClasses().get(name);
        if (clazz == null) {
            throw findException(name);
        }
        try {
            // 非Adaptive实现的实例对象,key=clazz,value=实例对象
            T instance = (T) EXTENSION_INSTANCES.get(clazz);
            if (instance == null) {
                // 对clazz实例化
                EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
                instance = (T) EXTENSION_INSTANCES.get(clazz);
            }
            // 这里是熟悉的dubbo的IOC功能;
            injectExtension(instance);
            // 这是dubbo的AOP功能;
            // cachedWrapperClasses存放的是,非Adaptive实现类中有 当前SPI类型的构造器;
            Set<Class<?>> wrapperClasses = cachedWrapperClasses;
            if (wrapperClasses != null && !wrapperClasses.isEmpty()) {
                for (Class<?> wrapperClass : wrapperClasses) {
                    // wrapperClass.getConstructor(type).newInstance(instance) 实例化这些Wrapper实现类,参数是当前name指定的实现类,其实就是通过Wrapper包装一层
                    instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
                }
            }
            return instance;
        } catch (Throwable t) {
            throw new IllegalStateException("Extension instance(name: " + name + ", class: " +
                    type + ")  could not be instantiated: " + t.getMessage(), t);
        }
}

这里对dubbo的AOP增强做下说明:

比如:Protocol,它的实现中有三个Wrapper:

  • ProtocolFilterWrapper
  • ProtocolListenerWrapper
  • QosProtocolWrapper

他们都有相似的地方是:

public QosProtocolWrapper(Protocol protocol) {
        if (protocol == null) {
            throw new IllegalArgumentException("protocol == null");
        }
        this.protocol = protocol;
}

构造方法中都有Protocol,这种在处理时会将它们加入到cachedWrapperClasses,而在使用Protocol的实现类时,这三个会进行实现类的功能增强;

2.5 Compiler SPI

在上面的com.alibaba.dubbo.common.extension.ExtensionLoader#createAdaptiveExtensionClass位置跳过了这段代码,现在来分析一下它的作用;

com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
compiler.compile(code, classLoader);

首先确定Compiler是一个SPI,@SPI("javassist")它的默认实现是javassist,它有一个编码实现的Adaptive实现类:AdaptiveCompiler

@Adaptive
public class AdaptiveCompiler implements Compiler {

    private static volatile String DEFAULT_COMPILER;

    public static void setDefaultCompiler(String compiler) {
        DEFAULT_COMPILER = compiler;
    }

    @Override
    public Class<?> compile(String code, ClassLoader classLoader) {
        Compiler compiler;
        // 获取Compiler的ExtensionLoader对象;
        ExtensionLoader<Compiler> loader = ExtensionLoader.getExtensionLoader(Compiler.class);
        // 如果没有调setDefaultCompiler方法,那么这里的DEFAULT_COMPILER是null
        String name = DEFAULT_COMPILER; // copy reference
        if (name != null && name.length() > 0) {
            compiler = loader.getExtension(name);
        } else {
            // 默认的是javassist实现:JavassistCompiler
            // 通过javassist动态编译成Class对象;
            compiler = loader.getDefaultExtension();
        }
        return compiler.compile(code, classLoader);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值