dubbo中ExtensionLoader解析

在上一篇《java中spi机制解读》中指出java的SPI机制存在以下缺点:只能获取配置中所有的接口实现,不能按照需要获取。所以ExtensionLoader加强了java中SPI机制的功能:可以按照名字加载实现类;在加载实现类过程中新增

本文以获取Protocol接口实现类为例进行说明:

 private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();

当我们调用getExtensionLoader这个静态方法的时候,会触发ExtensionLoader类的实例化,会先初始化静态变量和静态块,然后是构造代码块,最后是构造器的初始化

public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
    	//判断type是否为空,是否是接口类型,是否是以SPI为注解
        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!");
        }

        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);
        }
        return loader;
    }
private static final ConcurrentMap<Class<?>,ExtensionLoader<?>> EXTENSION_LOADERS=new ConcurrentHashMap<Class<?>,ExtensionLoader<?>>();

变量用于缓存所有的扩展加载实例;每个定义的spi的接口都会构建一个ExtensionLoader实例。

此时type类型为Protocol.class,以type为key值从EXTENSION_LOADERS变量中获取为null,此时创建一个ExtensionLoader即new ExtensionLoader<T>(type);调用ExtensionLoader的构造函数

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

因为此时type不等于ExtensionFactory.class所以执行后面用ExtensionLoader获取扩展类,接着调用getAdaptiveExtension()方法获取相关的扩展类

public T getAdaptiveExtension() {
    	//先从实例缓存中查找实例对象;在当前的ExtensionLoader中保存着一个Holder实例,用来缓存自适应实现类的实例
        Object instance = cachedAdaptiveInstance.get();
        if (instance == null) {//缓存中不存在
            if (createAdaptiveInstanceError == null) {
                synchronized (cachedAdaptiveInstance) {
                	//获取锁之后再检查一次缓存中是不是已经存在
                    instance = cachedAdaptiveInstance.get();
                    if (instance == null) {
                        try {
                        	 //缓存中没有,就创建新的AdaptiveExtension实例
                            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;
    }

这个类最后获得 获取一个扩展的自适应实现类,最后返回的自适应实现类是一个类名为Protocol$Adaptive的类,并且这个类实现了Protocol接口。

对于一个接口的实现者,ExtensionLoader分三种情况来分别存储对应的实现者,属性分别如下
Class<?> cachedAdaptiveClass;
Set<Class<?>> cachedWrapperClasses;
Reference<Map<String, Class<?>>> cachedClasses;

cachedAdaptiveClass:如果这个class含有Adaptive注解,则将这个class设置为Class<?> cachedAdaptiveClass

cachedWrapperClasses:尝试获取带对应接口参数的构造器,如果能够获取到,则说明这个class是一个装饰类即,需要存到Set<Class<?>> cachedWrapperClasses中

cachedClasses:如果没有上述构造器。则获取class上的Extension注解,根据该注解的定义的name作为key,存至Reference<Map<String, Class<?>>> cachedClasses结构中

创建自适应扩展

 private T createAdaptiveExtension() {
        try {
            //先通过getAdaptiveExtensionClass获取AdaptiveExtensionClass,获得到了一个自适应实现类的Class
            //然后获取其实例
            //最后进行注入处理
            return injectExtension((T) getAdaptiveExtensionClass().newInstance());
        } catch (Exception e) {
            throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
        }
    }

用来获取一个自适应扩展的Class

private Class<?> getAdaptiveExtensionClass() {
    	//加载当前Extension的所有实现(这里举例是Protocol,只会加载Protocol的所有实现类),如果有@Adaptive类型的实现类,会赋值给cachedAdaptiveClass
        //目前只有AdaptiveExtensionFactory和AdaptiveCompiler两个实现类是被注解了@Adaptive
        //除了ExtensionFactory和Compiler类型的扩展之外,其他类型的扩展都是下面动态创建的的实现
        getExtensionClasses();
        //加载完所有的实现之后,发现有cachedAdaptiveClass不为空
        //也就是说当前获取的自适应实现类是AdaptiveExtensionFactory或者是AdaptiveCompiler,就直接返回,这两个类是特殊用处的,不用代码生成,而是现成的代码
        if (cachedAdaptiveClass != null) {
            return cachedAdaptiveClass;
        }
        //没有找到Adaptive类型的实现,动态创建一个
        //比如Protocol的实现类,没有任何一个实现是用@Adaptive来注解的,只有Protocol接口的方法是有注解的
        //这时候就需要来动态的生成了,也就是生成Protocol$Adaptive
        return cachedAdaptiveClass = createAdaptiveExtensionClass();
    }

加载所有的扩展类的实现

private Map<String, Class<?>> getExtensionClasses() {
    	 //从缓存中获取,cachedClasses也是一个Holder,Holder这里持有的是一个Map,key是扩展点实现名,value是扩展点实现类
        //这里会存放当前扩展点类型的所有的扩展点的实现类
        //这里以Protocol为例,就是会存放Protocol的所有实现类
        //比如key为dubbo,value为com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol
        //cachedClasses扩展点实现名称对应的实现类
        Map<String, Class<?>> classes = cachedClasses.get();
      //如果为null,说明没有被加载过,就会进行加载,而且加载就只会进行这一次
        if (classes == null) {
            synchronized (cachedClasses) {
                classes = cachedClasses.get();
                if (classes == null) {
                	 //如果没有加载过Extension的实现,进行扫描加载,完成后缓存起来
                    //每个扩展点,其实现的加载只会这执行一次
                    classes = loadExtensionClasses();
                    cachedClasses.set(classes);
                }
            }
        }
        return classes;
    }

从不同目录加载扩展实现

private Map<String, Class<?>> loadExtensionClasses() {
    	// Dubbo的扩展接口必须实现SPI注解
        final SPI defaultAnnotation = type.getAnnotation(SPI.class);
        //这里是解析SPI注解,看是否有默认实现,后期Dubbo获取扩展的实现,如果获取不到就会有使用这个默认实现
        if (defaultAnnotation != null) {
        	 //当前Extension的默认实现名字
            //比如说Protocol接口,注解是@SPI("dubbo")
            //这里dubbo就是默认的值
            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];
            }
        }
        //从3个目录加载
        Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
        loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
        loadFile(extensionClasses, DUBBO_DIRECTORY);
        loadFile(extensionClasses, SERVICES_DIRECTORY);
        return extensionClasses;
    }

加载对应文件信息

private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
    	//配置文件的名称
        //这里type是扩展类,比如com.alibaba.dubbo.rpc.Protocol类
        String fileName = dir + type.getName();
        try {
            Enumeration<java.net.URL> urls;
            //获取类加载器
            ClassLoader classLoader = findClassLoader();
            //获取对应配置文件名的所有的文件
            if (classLoader != null) {
                urls = classLoader.getResources(fileName);
            } else {
                urls = ClassLoader.getSystemResources(fileName);
            }
            if (urls != null) {
            	//遍历文件进行处理
                while (urls.hasMoreElements()) {
                	//配置文件路径
                    java.net.URL url = urls.nextElement();
                    try {
                        BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8"));
                        try {
                            String line = null;
                            //每次处理一行
                            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;
                                        //=号之前的为扩展名字,后面的为扩展类实现的全限定名
                                        int i = line.indexOf('=');
                                        if (i > 0) {
                                        	// 文件采用properties方式的配置,name=实现类的全路径
                                            name = line.substring(0, i).trim();
                                            line = line.substring(i + 1).trim();
                                        }
                                        if (line.length() > 0) {
                                        	//加载扩展类的实现
                                            Class<?> clazz = Class.forName(line, true, classLoader);
                                            //查看类型是否匹配
                                            //type是Protocol接口
                                            //clazz就是Protocol的各个实现类
                                            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.");
                                            }
                                            
                                            
                                          //如果实现类是@Adaptive类型的,会赋值给cachedAdaptiveClass,这个用来存放被@Adaptive注解的实现类
                                            if (clazz.isAnnotationPresent(Adaptive.class)) {
                                                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());
                                                }
                                            } else {//不是@Adaptice类型的类,就是没有注解@Adaptive的实现类
                                                try {
                                                	//判断是否是wrapper类型
                                                	//如果得到的实现类的构造方法中的参数是扩展点类型的,就是一个Wrapper类
                                                    //比如ProtocolFilterWrapper,实现了Protocol类,
                                                    //而它的构造方法是这样public ProtocolFilterWrapper(Protocol protocol)
                                                    //就说明这个类是一个包装类
                                                    clazz.getConstructor(type);
                                                    Set<Class<?>> wrappers = cachedWrapperClasses;
                                                    if (wrappers == null) {
                                                        cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
                                                        wrappers = cachedWrapperClasses;
                                                    }
                                                    wrappers.add(clazz);
                                                } catch (NoSuchMethodException e) {
                                                	//没有上面提到的构造器,则说明不是wrapper类型
                                                	//获取无参构造
                                                    clazz.getConstructor();
                                                  //没有名字,就是配置文件中没有xxx=xxxx.com.xxx这种
                                                    if (name == null || name.length() == 0) {
                                                    	//去找@Extension注解中配置的值
                                                        name = findAnnotationName(clazz);
                                                        //如果还没找到名字,从类名中获取
                                                        if (name == null || name.length() == 0) {
                                                        	//比如clazz是DubboProtocol,type是Protocol
                                                            //这里得到的name就是dubbo
                                                            if (clazz.getSimpleName().length() > type.getSimpleName().length()
                                                                    && clazz.getSimpleName().endsWith(type.getSimpleName())) {
                                                                name = clazz.getSimpleName().substring(0, clazz.getSimpleName().length() - type.getSimpleName().length()).toLowerCase();
                                                            } else {
                                                                throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + url);
                                                            }
                                                        }
                                                    }
                                                    //有可能配置了多个名字
                                                    String[] names = NAME_SEPARATOR.split(name);
                                                    if (names != null && names.length > 0) {
                                                    	//是否是Active类型的类
                                                        Activate activate = clazz.getAnnotation(Activate.class);
                                                        if (activate != null) {
                                                        	//第一个名字作为键,放进cachedActivates这个map中缓存
                                                            cachedActivates.put(names[0], activate);
                                                        }
                                                        for (String n : names) {
                                                            if (!cachedNames.containsKey(clazz)) {
                                                            	//放入Extension实现类与名称映射的缓存中去,每个class只对应第一个名称有效
                                                                cachedNames.put(clazz, n);
                                                            }
                                                            Class<?> c = extensionClasses.get(n);
                                                            if (c == null) {
                                                            	 //放入到extensionClasses缓存中去,多个name可能对应一份extensionClasses
                                                                extensionClasses.put(n, clazz);
                                                            } else if (c != clazz) {
                                                                throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName());
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    } catch (Throwable t) {
                                        IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);
                                        exceptions.put(line, e);
                                    }
                                }
                            } // end of while read lines
                        } finally {
                            reader.close();
                        }
                    } catch (Throwable t) {
                        logger.error("Exception when load extension class(interface: " +
                                type + ", class file: " + url + ") in " + url, t);
                    }
                } // end of while urls
            }
        } catch (Throwable t) {
            logger.error("Exception when load extension class(interface: " +
                    type + ", description file: " + fileName + ").", t);
        }
    }

动态的创建自适应扩展类

private Class<?> createAdaptiveExtensionClass() {
    	//动态生成类似Protocol$Adaptive 代理;动态生成适配器代码
    	//组装自适应扩展点类的代码
        String code = createAdaptiveExtensionClassCode();
        //获取到应用的类加载器
        ClassLoader classLoader = findClassLoader();
        //获取编译器
        //dubbo默认使用javassist
        //这里还是使用扩展点机制来找具体的Compiler的实现
        //现在就知道cachedAdaptiveClass是啥意思了,如果没有AdaptiveExtensionFactory和AdaptiveCompiler这两个类,这里又要去走加载流程然后来生成扩展点类的代码,不就死循环了么。
        //这里解析Compiler的实现类的时候,会在getAdaptiveExtensionClass中直接返回
        //可以查看下AdaptiveCompiler这个类,如果我们没有指定,默认使用javassist
        //这里Compiler是JavassistCompiler实例
        com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
        //将代码转换成Class
        return compiler.compile(code, classLoader);
    }

生成代理类Adaptive

private String createAdaptiveExtensionClassCode() {
        StringBuilder codeBuidler = new StringBuilder();
        Method[] methods = type.getMethods();
        boolean hasAdaptiveAnnotation = false;
        for (Method m : methods) {
            if (m.isAnnotationPresent(Adaptive.class)) {
                hasAdaptiveAnnotation = true;
                break;
            }
        }
        // no need to generate adaptive class since there's no adaptive method found.
        if (!hasAdaptiveAnnotation)
            throw new IllegalStateException("No adaptive method on extension " + type.getName() + ", refuse to create the adaptive class!");

        codeBuidler.append("package " + type.getPackage().getName() + ";");
        codeBuidler.append("\nimport " + ExtensionLoader.class.getName() + ";");
        codeBuidler.append("\npublic class " + type.getSimpleName() + "$Adaptive" + " implements " + type.getCanonicalName() + " {");

        for (Method method : methods) {
            Class<?> rt = method.getReturnType();
            Class<?>[] pts = method.getParameterTypes();
            Class<?>[] ets = method.getExceptionTypes();

            Adaptive adaptiveAnnotation = method.getAnnotation(Adaptive.class);
            StringBuilder code = new StringBuilder(512);
            if (adaptiveAnnotation == null) {
                code.append("throw new UnsupportedOperationException(\"method ")
                        .append(method.toString()).append(" of interface ")
                        .append(type.getName()).append(" is not adaptive method!\");");
            } else {
                int urlTypeIndex = -1;
                for (int i = 0; i < pts.length; ++i) {
                    if (pts[i].equals(URL.class)) {
                        urlTypeIndex = i;
                        break;
                    }
                }
                // found parameter in URL type
                if (urlTypeIndex != -1) {
                    // Null Point check
                    String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"url == null\");",
                            urlTypeIndex);
                    code.append(s);

                    s = String.format("\n%s url = arg%d;", URL.class.getName(), urlTypeIndex);
                    code.append(s);
                }
                // did not find parameter in URL type
                else {
                    String attribMethod = null;

                    // find URL getter method
                    LBL_PTS:
                    for (int i = 0; i < pts.length; ++i) {
                        Method[] ms = pts[i].getMethods();
                        for (Method m : ms) {
                            String name = m.getName();
                            if ((name.startsWith("get") || name.length() > 3)
                                    && Modifier.isPublic(m.getModifiers())
                                    && !Modifier.isStatic(m.getModifiers())
                                    && m.getParameterTypes().length == 0
                                    && m.getReturnType() == URL.class) {
                                urlTypeIndex = i;
                                attribMethod = name;
                                break LBL_PTS;
                            }
                        }
                    }
                    if (attribMethod == null) {
                        throw new IllegalStateException("fail to create adaptive class for interface " + type.getName()
                                + ": not found url parameter or url attribute in parameters of method " + method.getName());
                    }

                    // Null point check
                    String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"%s argument == null\");",
                            urlTypeIndex, pts[urlTypeIndex].getName());
                    code.append(s);
                    s = String.format("\nif (arg%d.%s() == null) throw new IllegalArgumentException(\"%s argument %s() == null\");",
                            urlTypeIndex, attribMethod, pts[urlTypeIndex].getName(), attribMethod);
                    code.append(s);

                    s = String.format("%s url = arg%d.%s();", URL.class.getName(), urlTypeIndex, attribMethod);
                    code.append(s);
                }

                String[] value = adaptiveAnnotation.value();
                // value is not set, use the value generated from class name as the key
                if (value.length == 0) {
                    char[] charArray = type.getSimpleName().toCharArray();
                    StringBuilder sb = new StringBuilder(128);
                    for (int i = 0; i < charArray.length; i++) {
                        if (Character.isUpperCase(charArray[i])) {
                            if (i != 0) {
                                sb.append(".");
                            }
                            sb.append(Character.toLowerCase(charArray[i]));
                        } else {
                            sb.append(charArray[i]);
                        }
                    }
                    value = new String[]{sb.toString()};
                }

                boolean hasInvocation = false;
                for (int i = 0; i < pts.length; ++i) {
                    if (pts[i].getName().equals("com.alibaba.dubbo.rpc.Invocation")) {
                        // Null Point check
                        String s = String.format("\nif (arg%d == null) throw new IllegalArgumentException(\"invocation == null\");", i);
                        code.append(s);
                        s = String.format("\nString methodName = arg%d.getMethodName();", i);
                        code.append(s);
                        hasInvocation = true;
                        break;
                    }
                }

                String defaultExtName = cachedDefaultName;
                String getNameCode = null;
                for (int i = value.length - 1; i >= 0; --i) {
                    if (i == value.length - 1) {
                        if (null != defaultExtName) {
                            if (!"protocol".equals(value[i]))
                                if (hasInvocation)
                                    getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
                                else
                                    getNameCode = String.format("url.getParameter(\"%s\", \"%s\")", value[i], defaultExtName);
                            else
                                getNameCode = String.format("( url.getProtocol() == null ? \"%s\" : url.getProtocol() )", defaultExtName);
                        } else {
                            if (!"protocol".equals(value[i]))
                                if (hasInvocation)
                                    getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
                                else
                                    getNameCode = String.format("url.getParameter(\"%s\")", value[i]);
                            else
                                getNameCode = "url.getProtocol()";
                        }
                    } else {
                        if (!"protocol".equals(value[i]))
                            if (hasInvocation)
                                getNameCode = String.format("url.getMethodParameter(methodName, \"%s\", \"%s\")", value[i], defaultExtName);
                            else
                                getNameCode = String.format("url.getParameter(\"%s\", %s)", value[i], getNameCode);
                        else
                            getNameCode = String.format("url.getProtocol() == null ? (%s) : url.getProtocol()", getNameCode);
                    }
                }
                code.append("\nString extName = ").append(getNameCode).append(";");
                // check extName == null?
                String s = String.format("\nif(extName == null) " +
                                "throw new IllegalStateException(\"Fail to get extension(%s) name from url(\" + url.toString() + \") use keys(%s)\");",
                        type.getName(), Arrays.toString(value));
                code.append(s);

                s = String.format("\n%s extension = (%<s)%s.getExtensionLoader(%s.class).getExtension(extName);",
                        type.getName(), ExtensionLoader.class.getSimpleName(), type.getName());
                code.append(s);

                // return statement
                if (!rt.equals(void.class)) {
                    code.append("\nreturn ");
                }

                s = String.format("extension.%s(", method.getName());
                code.append(s);
                for (int i = 0; i < pts.length; i++) {
                    if (i != 0)
                        code.append(", ");
                    code.append("arg").append(i);
                }
                code.append(");");
            }

            codeBuidler.append("\npublic " + rt.getCanonicalName() + " " + method.getName() + "(");
            for (int i = 0; i < pts.length; i++) {
                if (i > 0) {
                    codeBuidler.append(", ");
                }
                codeBuidler.append(pts[i].getCanonicalName());
                codeBuidler.append(" ");
                codeBuidler.append("arg" + i);
            }
            codeBuidler.append(")");
            if (ets.length > 0) {
                codeBuidler.append(" throws ");
                for (int i = 0; i < ets.length; i++) {
                    if (i > 0) {
                        codeBuidler.append(", ");
                    }
                    codeBuidler.append(ets[i].getCanonicalName());
                }
            }
            codeBuidler.append(" {");
            codeBuidler.append(code.toString());
            codeBuidler.append("\n}");
        }
        codeBuidler.append("\n}");
        if (logger.isDebugEnabled()) {
            logger.debug(codeBuidler.toString());
        }
        return codeBuidler.toString();
    }

以Protocol为例,生成的代理类代码为

package com.alibaba.dubbo.rpc;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
public class Protocol$Adaptive implements com.alibaba.dubbo.rpc.Protocol {

	public void destroy() {
		throw new UnsupportedOperationException("method public abstract void com.alibaba.dubbo.rpc.Protocol.destroy() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
	}
	
	public int getDefaultPort() {
		throw new UnsupportedOperationException("method public abstract int com.alibaba.dubbo.rpc.Protocol.getDefaultPort() of interface com.alibaba.dubbo.rpc.Protocol is not adaptive method!");
	}
	
	public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws com.alibaba.dubbo.rpc.RpcException {
		if (arg1 == null) throw new IllegalArgumentException("url == null");
		com.alibaba.dubbo.common.URL url = arg1;
		String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
		if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
		//根据extName属性来获取需要加载的接口实现类
		com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
		return extension.refer(arg0, arg1);
	}
	public com.alibaba.dubbo.rpc.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.RpcException {
		if (arg0 == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument == null");
		if (arg0.getUrl() == null) throw new IllegalArgumentException("com.alibaba.dubbo.rpc.Invoker argument getUrl() == null");com.alibaba.dubbo.common.URL url = arg0.getUrl();
		String extName = ( url.getProtocol() == null ? "dubbo" : url.getProtocol() );
		if(extName == null) throw new IllegalStateException("Fail to get extension(com.alibaba.dubbo.rpc.Protocol) name from url(" + url.toString() + ") use keys([protocol])");
		com.alibaba.dubbo.rpc.Protocol extension = (com.alibaba.dubbo.rpc.Protocol)ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(extName);
		return extension.export(arg0);
	}
}

动态的加载接口实现类,是接口和具体实现分开

获取编译器

com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
这里还是使用扩展点机制来找具体的Compiler的实现,这里Compiler是JavassistCompiler实例;最终将代码转换成Class。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值