美文网首页
ExtensionLoader扩展点加载

ExtensionLoader扩展点加载

作者: 一滴水的坚持 | 来源:发表于2018-02-06 10:43 被阅读0次
    官方文档.png
    在官方文档中,提到扩展点加载机制,不妨看看是如何实现的。
    扩展点加载机制,最重要的类就是ExtensionLoader
    getExtensionLoader的实现原理

    在获取扩展加载器的时候,首先会判断是否有注解SPI,没有则抛异常,有SPI注解的前提下,先从缓存取,取不到,根据class类型新建一个新的扩展点加载器。

    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.putIfAbsent(type, new ExtensionLoader<T>(type));
                loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
            }
            return loader;
        }
    

    在新增加载点扩展器的时候,会根据class类型获取一个运行期自适应的扩展类型

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

    我们看到,如果类型不是ExtensionFactory,则从ExtensionFactory的扩展加载器中获取一个可扩展的的加载器。这里先不看ExtensionFactory,先看一下获取可扩展加载器方法。

    getAdaptiveExtension获取可调整的扩展加载器

    在获取可扩展加载器的时候,先从缓存获取,若缓存不存在,创建新的扩展加载器。在创建新的扩展加载器的时候,首先判断配置文件中(META-INF/dubbo/META-INF/services/,META-INF/dubbo/internal)配置的class是否有被Adaptive注解的类,如果有,则直接返回被注解Adaptive的可扩展加载类,如果没有,则生成一个扩展类。

    public T getAdaptiveExtension() {
            //先从缓存中获取
            Object instance = cachedAdaptiveInstance.get();
            if (instance == null) {
                if (createAdaptiveInstanceError == null) {
                    synchronized (cachedAdaptiveInstance) {
                        instance = cachedAdaptiveInstance.get();
                        if (instance == null) {
                            try {
                                //创建一个新的可扩展加载器
                                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;
        }
    
        private T createAdaptiveExtension() {
             //根据可扩展实例做扩展
            try {
                return injectExtension((T) getAdaptiveExtensionClass().newInstance());
            } catch (Exception e) {
                throw new IllegalStateException("Can not create adaptive extension " + type + ", cause: " + e.getMessage(), e);
            }
        }
    
       //获取可扩展实例
        private Class<?> getAdaptiveExtensionClass() {
          // 加载当前Extension的所有实现,如果有@Adaptive类型,则会赋值为cachedAdaptiveClass属性缓存起来
            getExtensionClasses();
            if (cachedAdaptiveClass != null) {
                //如果缓存有可扩展类,则直接返回
                return cachedAdaptiveClass;
            }
            //缓存中不存在创建一个
            return cachedAdaptiveClass = createAdaptiveExtensionClass();
        }
    
     获取可扩展类 
     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;
        }
    
      从配置文件中加载
      private Map<String, Class<?>> loadExtensionClasses() {
            final SPI defaultAnnotation = type.getAnnotation(SPI.class);
             //忽略1w行代码
            // 文件路径: 
            loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);
            //文件路径
            loadFile(extensionClasses, DUBBO_DIRECTORY);
            //文件路径 
            loadFile(extensionClasses, SERVICES_DIRECTORY);
            return extensionClasses;
        }
    //根据文件名(包路径)查找所有文件,将每一行的配置读取出来,判断是否是实现该接口的类,如果接口中有注解`Adaptive`,则更新`cachedAdaptiveClass`的值。
    private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
       //文件路径为基本路径+包路径
       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"));
                            //读每一行数据,判断=之前为bean的ID,后面为bean的class类型
                            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<?> clazz = Class.forName(line, true, classLoader);
                                                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.");
                                                }
                                                if (clazz.isAnnotationPresent(Adaptive.class)) {
                                                    //如果该类注解了Adaptive注解,则更新cachedAdaptiveClass为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 {
                                                    try {
                                                        clazz.getConstructor(type);
                                                        Set<Class<?>> wrappers = cachedWrapperClasses;
                                                        if (wrappers == null) {
                                                            cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
                                                            wrappers = cachedWrapperClasses;
                                                        }
                                                        wrappers.add(clazz);
                                                    } catch (NoSuchMethodException e) {
                                                        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);
                                                            if (activate != null) {
                                                                cachedActivates.put(names[0], activate);
                                                            }
                                                            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);
            }
    

    如果没有被注解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);
        }
    

    在对可扩展实例做扩展,会根据代理工厂创建一个实例,在构造方法中,使用的是ExtensionFactory的扩展

    private T injectExtension(T instance) {
            try {
                if (objectFactory != null) {
                    for (Method method : instance.getClass().getMethods()) {
                        if (method.getName().startsWith("set")
                                && method.getParameterTypes().length == 1
                                && Modifier.isPublic(method.getModifiers())) {
                            Class<?> pt = method.getParameterTypes()[0];
                            try {
                                String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";
                                //获取扩展实例
                                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;
        } 
    

    看一下 ExtensionFactory的定义,和实现

    @SPI
    public interface ExtensionFactory {
       <T> T getExtension(Class<T> type, String name);
    }
    
    
    @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);
       }
    
       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;
       }
    }
    
    public class SpiExtensionFactory implements ExtensionFactory {
    
       public <T> T getExtension(Class<T> type, String name) {
           if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
               ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
               if (loader.getSupportedExtensions().size() > 0) {
                   return loader.getAdaptiveExtension();
               }
           }
           return null;
       }
    
    }
    
    
    public class SpringExtensionFactory implements ExtensionFactory {
    
       private static final Set<ApplicationContext> contexts = new ConcurrentHashSet<ApplicationContext>();
    
       public static void addApplicationContext(ApplicationContext context) {
           contexts.add(context);
       }
    
       public static void removeApplicationContext(ApplicationContext context) {
           contexts.remove(context);
       }
    
       @SuppressWarnings("unchecked")
       public <T> T getExtension(Class<T> type, String name) {
           for (ApplicationContext context : contexts) {
               if (context.containsBean(name)) {
                   Object bean = context.getBean(name);
                   if (type.isInstance(bean)) {
                       return (T) bean;
                   }
               }
           }
           return null;
       }
    
    }
    

    很显然,在这里用到的是AdaptiveExtensionFactory,因为它被注解@Adaptive注解了,然后从ExtensionFactory中获取扩展加载类。

    相关文章

      网友评论

          本文标题:ExtensionLoader扩展点加载

          本文链接:https://www.haomeiwen.com/subject/rphizxtx.html