zoukankan      html  css  js  c++  java
  • Dubbo-SPI应用

      Dubbo 自己实现的SPI 用于获取一个实现类的对象

      一、为什么Dubbo要自己设计一套SPI

        1.原始的JDK SPI不支持缓存: Dubbo设计了缓存对象-cachedInstances 是一个 new ConcurrentHashMap<String, Holder<Object>>()

        2.原始JDK SPI不支持默认值: Dubbo设计默认值 -@SPI("dubbo")代表默认的spi对象

          例如 Protocol的@SPI("dubbo")就是DubboProtocol通过ExtensionLoader.getExtensionLoader(Protocol.class).getDefaultExtension()拿默认对象

        3.JDK要使用For循环判断对象: Dubbo设计的getExtension灵活方便,动态获取spi对象

          例如 ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(spi的key)来提取对象

        4.原始JDK不支持AOP功能: Dubbo设计增加了AOP功能,在cachedWrapperClasses,在原始类,包装了XxxxFilterWrapper XxxxListenerWrapper

          例如  ProtocolFilterWrapper

        5.原始JDK不支持IOC功能: Dubbo设计增加了IOC,通过构造函数注入代码

          例如 wrapperClass.getConstructor(type).newInstance(instance) 

            首先获得自适应扩展点的Class对象,然后通过反射获取实例,将对象创建的权力交给框架,这就是控制反转

      二、Dubbo中实现路径

        途径:

          ExtensionLoader.getExtension(String name)

        实现路径:

          getExtensionLoader(Class<T> type) new 一个ExtensionLoader,然后缓存起来

          getAdaptiveExtension() 获取一个扩展装饰类的对象,这个类有一个规则,如果它没有一个@Adaptive注解,就动态创建一个代理类.例如 Protocol$Adaptive对象

          getExtension(String name) 获取一个对象

    public class ExtensionLoader<T> {
    
        private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class);
        
        private static final String SERVICES_DIRECTORY = "META-INF/services/";
    
        private static final String DUBBO_DIRECTORY = "META-INF/dubbo/";
        
        private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";
    
        private static final Pattern NAME_SEPARATOR = Pattern.compile("\s*[,]+\s*");
        
        private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>(); // 缓存spi对象和Extension对象的映射
    
        private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, Object>();
    
        // ==============================
    
        private final Class<?> type;
    
        private final ExtensionFactory objectFactory;
    
        private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>(); // 缓存扩展实现类与name的映射关系
        
        private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String,Class<?>>>(); // 将缓存loadFile方法的入参,extensionClasses存储的是扩展实现类name和Class对象的映射
    
        private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>(); // 缓存扩展实现类name与激活信息的映射
    
        private volatile Class<?> cachedAdaptiveClass = null; //缓存@Adaptive的扩展实现类型
    
        private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();
    
        private String cachedDefaultName;
    
        private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();  // adaptive的缓存对象
        private volatile Throwable createAdaptiveInstanceError;
    
        private Set<Class<?>> cachedWrapperClasses; // 缓存扩展实现类中的wrapper包装类
        
        private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<String, IllegalStateException>();
        
        private static <T> boolean withExtensionAnnotation(Class<T> type) {
            return type.isAnnotationPresent(SPI.class);
        }
    .......
    }
    

        

    三、代码流程

      -->getExtensionLoader(Class<T> type)

        -->new ExtensionLoader<T>(type)

          -->ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension())

            -->getAdaptiveExtension()   为cachedAdaptiveInstance赋值

              -->createAdaptiveExtension()

                --> injectExtension((T) getAdaptiveExtensionClass().newInstance())    这里运用了IOC 以及 DI 思想

                  -->getAdaptiveExtensionClass

                    -->getExtensionClasses() 为cachedClasses赋值

                      -->loadExtensionClasses()

                        -->loadFile(Map<String, Class<?>> extensionClasses, String dir)  加载文件中的类路径 已经将类存入 cachedAdaptiveClass,cachedWrapperClasses,cachedActivates,cachedNames

                    -->createAdaptiveExtensionClass() 自动生成和编译一个动态的adadtive代理类

                      -->createAdaptiveExtensionClassCode()  生成对应的代理类代码

                      --> com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension()

                      -->compiler.compile(code, classLoader)  生成对应类对象

                        -->getExtension(String name)  返回指定名称的扩展

                          -->createExtension(String name)

                            -->getExtensionClasses 获取对应所有类对象

                            -->injectExtension(instance)

                  -->injectExtension(T instance)  进入IOC的反转控制模式,实现了动态注入

                    -->objectFactory.getExtension(pt, property)

                      -->SpiExtensionFactory.getExtension(type,name)

                        -->ExtensionLoader.getExtensionLoader(type)

                        -->loader.getAdaptiveExtension()

                      -->SpringExtensionFactory.getExtension(type,name)

                        -->context.getBean(name)

    四、代码解析

      dubbo入口   com.alibaba.dubbo.container.Main

    public class Main {
    
        public static final String CONTAINER_KEY = "dubbo.container";
    
        public static final String SHUTDOWN_HOOK_KEY = "dubbo.shutdown.hook";
        
        private static final Logger logger = LoggerFactory.getLogger(Main.class);
    
        private static final ExtensionLoader<Container> loader = ExtensionLoader.getExtensionLoader(Container.class);
        
        private static volatile boolean running = true;
    
        public static void main(String[] args) {
            try {
                if (args == null || args.length == 0) {
                    String config = ConfigUtils.getProperty(CONTAINER_KEY, loader.getDefaultExtensionName());
                    args = Constants.COMMA_SPLIT_PATTERN.split(config);
                }
                
                final List<Container> containers = new ArrayList<Container>();
                for (int i = 0; i < args.length; i ++) {
                    containers.add(loader.getExtension(args[i]));
                }
                logger.info("Use container type(" + Arrays.toString(args) + ") to run dubbo serivce.");
                
                if ("true".equals(System.getProperty(SHUTDOWN_HOOK_KEY))) {
    	            Runtime.getRuntime().addShutdownHook(new Thread() {
    	                public void run() {
    	                    for (Container container : containers) {
    	                        try {
    	                            container.stop();
    	                            logger.info("Dubbo " + container.getClass().getSimpleName() + " stopped!");
    	                        } catch (Throwable t) {
    	                            logger.error(t.getMessage(), t);
    	                        }
    	                        synchronized (Main.class) {
    	                            running = false;
    	                            Main.class.notify();
    	                        }
    	                    }
    	                }
    	            });
                }
                
                for (Container container : containers) {
                    container.start(); // 启动容器方法
                    logger.info("Dubbo " + container.getClass().getSimpleName() + " started!");
                }
                System.out.println(new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]").format(new Date()) + " Dubbo service server started!");
            } catch (RuntimeException e) {
                e.printStackTrace();
                logger.error(e.getMessage(), e);
                System.exit(1);
            }
            synchronized (Main.class) {
                while (running) {
                    try {
                        Main.class.wait();
                    } catch (Throwable e) {
                    }
                }
            }
        }
        
    }
    从 EXTENSION_LOADERS(存储SPI对象和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!");
            }
            // 从缓存中获取该对象
            ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
            if (loader == null) {
           // 此处使用putIfAbsent 有值就返回,不和put一样有替换的操作 EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); } return loader; }

      缓存中不存在,组建ExtensionLoader对象,组建type+objectFactory对象

      objectFactory 它就是为dubbo的IOC提供所有对象

    private ExtensionLoader(Class<?> type) {
            this.type = type;
            objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
        }
    @Adaptive 
      注解在类上: 代表人工编码实现,Dubbo不会为该类生成代理类 例如 ExtensionFactory
      注解在方法上: Dubbo会为该方法实现代理逻辑 例如Protocol$Adaptive

    获取对应Adaptive对象,然后放入cachedAdaptiveInstance 缓存中

    public T getAdaptiveExtension() {
          // 获取 adaptive缓存对象 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; }

      创建自适应的扩展类      newInstance传教兑现实例 

    private T createAdaptiveExtension() {
            try {
           // 获取该对象 实例化后注入extension return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e); } }

      获取自适应扩展点的细节

    private Class<?> getAdaptiveExtensionClass() {
            getExtensionClasses();
            if (cachedAdaptiveClass != null) { // 如果扩展点的实现类有@Adaptive注解,则直接返回该实现类
                return cachedAdaptiveClass;
            }
          // 否则创建自适应的代理类 return cachedAdaptiveClass = createAdaptiveExtensionClass(); }
    spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory
    cachedClasses存储类似spring 与 com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory 对应关系
    获取所有的扩展类
    private Map<String, Class<?>> getExtensionClasses() {
        // 从缓存中获取已加载的扩展类 Map<String, Class<?>> classes = cachedClasses.get(); // 双重检查
        if (classes == null) { synchronized (cachedClasses) { classes = cachedClasses.get(); if (classes == null) { // 加载扩展类
                classes = loadExtensionClasses(); cachedClasses.set(classes); } } } return classes; }

      

       先检查缓存,若缓存没有命中,则通过synchronized加锁,加锁后再次验证缓存,若classes任为null,则通过loadExtensionClasses加载扩展类

     加载对应class 类

    // 此方法已经getExtensionClasses方法同步过。
        private Map<String, Class<?>> loadExtensionClasses() {
            // 获取SPI注解,这里的type变量是在调用getExtensionLoader方法传入的
         final SPI defaultAnnotation = type.getAnnotation(SPI.class); if(defaultAnnotation != null) { String value = defaultAnnotation.value(); if(value != null && (value = value.trim()).length() > 0) { // 对SPI注解内容进行切分
              String[] names = NAME_SEPARATOR.split(value); if(names.length > 1) { //检测SPI注解内容是否合法,不合法抛出异常 throw new IllegalStateException("more than 1 default extension name on extension " + type.getName() + ": " + Arrays.toString(names)); } if(names.length == 1) cachedDefaultName = names[0]; } } Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>(); loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY); // 真正使用这一行 loadFile(extensionClasses, DUBBO_DIRECTORY); loadFile(extensionClasses, SERVICES_DIRECTORY); return extensionClasses; }

     loadExtensionClasses方法总共做了两件事情

      1.对SPI注解进行解析

      2.调用loadDirectory方法加载指定文件夹配置文件

     加载配置文件信息拿到对应className

    private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
          // 拼装相对路径 类似 META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Protocol String fileName = dir + type.getName();
    try { Enumeration<java.net.URL> urls; ClassLoader classLoader = findClassLoader(); if (classLoader != null) {
                       // getResources() 获取项目文件 urls = classLoader.getResources(fileName); } else {
                // 使用系统的classLoader然后调用getResource 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) { name = line.substring(0, i).trim(); line = line.substring(i + 1).trim(); } if (line.length() > 0) {
                                // 那对对应class Class<?> clazz = Class.forName(line, true, classLoader);
                                 // isAssignableFrom type对象所表示的类或者接口,与clazz所表示的类是否是其超类或者超接口,是 返回true,否 返回false 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 加入到对应 cacheAdaptiveClass 缓存中 clazz类上是否有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 {
                                    // 无@Adaptive注解 try {
                                    // 匹配对应的构造参数 ,只有当该class有目标接口构造方法 进入 cacheWarapperClasses缓存 类似 ProtocolFilterWarppeer 和 ProtocolListenerWarpper符合条件 clazz.getConstructor(type); Set<Class<?>> wrappers = cachedWrapperClasses; if (wrappers == null) { cachedWrapperClasses = new ConcurrentHashSet<Class<?>>(); wrappers = cachedWrapperClasses; } wrappers.add(clazz); } catch (NoSuchMethodException e) {
                                      // 其他无参构造 进入cacheActivates和cacheNames缓存 clazz.getConstructor(); if (name == null || name.length() == 0) { name = findAnnotationName(clazz); if (name == null || name.length() == 0) { 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) { Activate activate = clazz.getAnnotation(Activate.class);
                                        // 有@Activate注解的进入cachedActivates缓存 if (activate != null) { cachedActivates.put(names[0], activate); }
                                        // 排除wrapper 的类其他类进入cacheNames中 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()); } } } } } } } 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); } }
     loadDirectory方法刷线通过classLoader获取所有的资源链接,然后读取其中内容,通过反射加载类,并操作chachedAdaptiveClass、cachedWrapperClasses和cachedNames等缓存
    ProtocolListenerWrapper 符合 clazz.getConstructor(type); 条件

     

     创建对应的包装类--自动生成一个动态的 adaptive 类

    private Class<?> createAdaptiveExtensionClass() {
            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);
        }

     生成对应代理类的code代码

    private String createAdaptiveExtensionClassCode() {
            StringBuilder codeBuidler = new StringBuilder();
            Method[] methods = type.getMethods();
            boolean hasAdaptiveAnnotation = false;
          // 判断所有的方法上有没有@Adaptive注解 for(Method m : methods) { if(m.isAnnotationPresent(Adaptive.class)) { hasAdaptiveAnnotation = true; break; } } // 完全没有Adaptive方法,则不需要生成Adaptive类 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(" import " + ExtensionLoader.class.getName() + ";"); codeBuidler.append(" public class " + type.getSimpleName() + "$Adpative" + " 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; } } // 有类型为URL的参数 if (urlTypeIndex != -1) { // Null Point check String s = String.format(" if (arg%d == null) throw new IllegalArgumentException("url == null");", urlTypeIndex); code.append(s); s = String.format(" %s url = arg%d;", URL.class.getName(), urlTypeIndex); code.append(s); } // 参数没有URL类型 else { String attribMethod = null; // 找到参数的URL属性 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 adative 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(" if (arg%d == null) throw new IllegalArgumentException("%s argument == null");", urlTypeIndex, pts[urlTypeIndex].getName()); code.append(s); s = String.format(" if (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(); // 没有设置Key,则使用“扩展点接口名的点分隔 作为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(" if (arg%d == null) throw new IllegalArgumentException("invocation == null");", i); code.append(s); s = String.format(" String 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(" String extName = ").append(getNameCode).append(";"); // check extName == null? String s = String.format(" if(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(" %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(" return "); } 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(" public " + 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(pts[i].getCanonicalName()); } } codeBuidler.append(" {"); codeBuidler.append(code.toString()); codeBuidler.append(" }"); } codeBuidler.append(" }"); if (logger.isDebugEnabled()) { logger.debug(codeBuidler.toString()); } return codeBuidler.toString(); }

     默认生成的code代码类-发现@Adaptive 注解的都没有实现

    public class Protocol$Adpative 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.Exporter export(com.alibaba.dubbo.rpc.Invoker arg0) throws com.alibaba.dubbo.rpc.Invoker {
            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);
        }
    
        public com.alibaba.dubbo.rpc.Invoker refer(java.lang.Class arg0, com.alibaba.dubbo.common.URL arg1) throws java.lang.Class {
            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])");
            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 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) {
    		    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) {
            Class<?> clazz = getExtensionClasses().get(name);
            if (clazz == null) {
                throw findException(name);
            }
            try {
                T instance = (T) EXTENSION_INSTANCES.get(clazz);
                if (instance == null) {
                    EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());
                    instance = (T) EXTENSION_INSTANCES.get(clazz);
                }
                injectExtension(instance);
                Set<Class<?>> wrapperClasses = cachedWrapperClasses;
                if (wrapperClasses != null && wrapperClasses.size() > 0) {
                    for (Class<?> wrapperClass : wrapperClasses) {
                        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 IOC 
      dubbo ioc是通过setter方法注入依赖,Dubbo首先通过反射获取到实例的所有方法,然后通过遍历方法列表,检查方法名中是否具有setter方法特征
        若有:则通过ObjectFactory获取依赖对象,最后通过反射调用setter方法将依赖设置到目标对象中
    private T injectExtension(T instance) {
            try {
                if (objectFactory != null) {
              // 提取所有方法 for (Method method : instance.getClass().getMethods()) {
                // 查询是否有set方法 且方法只有一个参数,且方法访问级别是public if (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && Modifier.isPublic(method.getModifiers())) { Class<?> pt = method.getParameterTypes()[0]; try { // 获取属性名,比如setName 方法对应属性名name String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : ""; // 从ObjectFactory中获取依赖对象
                     Object object = objectFactory.getExtension(pt, property); if (object != null) { // 通过反射调用setter方法设置依赖
                        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; }

      objectFactory变量的类型是AdaptiveExtensionFactory。

        AdaptiveExtensionFactory内部维护了一个叫做ExtensionFactory列表,用于存储其他类型的ExtensionFactory。

        Dubbo目前提供两种ExtensionFactory,分别是SpiExtensionFactory和SpringExtensionFactory。

          前者用于创建自适应的扩展,后者用于从spring的IOC容器中获取所需要的扩展

     

    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;
        }
    

      

     

  • 相关阅读:
    数据库字段太多,批量快速建立实体类方法(适合大量字段建立实体类)
    SQL service 中的 ”输入SQL命令窗口“ 打开了 “属性界面” 回到 ”输入SQL命令窗口“
    计算机软件编程英语词汇集锦
    编程常用英语词汇
    svn上传和下载项目
    当启动tomcat时出现tomcat setting should be set in tomcat preference page
    Implicit super constructor Object() is undefined for default constructor. Must define an explicit constructor
    eclipse中选中一个单词 其他相同的也被选中 怎么设置
    Spring Boot的@SpringBootApplication无法引入的问题
    最全的SpringCloud视频教程
  • 原文地址:https://www.cnblogs.com/huan30/p/12723574.html
Copyright © 2011-2022 走看看