美文网首页
spring-类SPI机制-SpringFactoriesLoa

spring-类SPI机制-SpringFactoriesLoa

作者: Mr_1214 | 来源:发表于2018-05-19 19:48 被阅读38次

spring的默认扩展放在META-INF/spring.factories下,文件的格式如下:

# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration

SpringFactoriesLoader 默认提供loadFactories,loadFactoryNames,instantiateFactory三个方法,其中loadFactories根据参数factoryClass获取spring.factories下配置的所有实现类实例。loadFactoryNames 根据参数factoryClass获取spring.factories下配置的所有实现类名
instantiateFactory方法是根据实现类名反射获取实现类实例

方法:loadFactories

public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {
        //获取类的ClassLoader
        ClassLoader classLoaderToUse = classLoader;
        if(classLoader == null) {
            classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }

        //调用loadFactoryNames获取所有实现类的名称集合
        List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse);
        if(logger.isTraceEnabled()) {
            logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames);
        }

        List<T> result = new ArrayList(factoryNames.size());
        Iterator var5 = factoryNames.iterator();

        //调用instantiateFactory方法获取给定类名的类实现实例
        while(var5.hasNext()) {
            String factoryName = (String)var5.next();
            result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
        }

        //对集合排序
        AnnotationAwareOrderComparator.sort(result);
        return result;
    }

通过源码可以看到loadFactories方法主要通过了loadFactoryNames与instantiateFactory完成整个功能的实现。

方法:loadFactoryNames

public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
         //获取扩展类的全名字符传
        String factoryClassName = factoryClass.getName();

        try {
         // 通过classLoader加载环境中所有jar目录下的META-INF/spring.factories,获取文件集合
            Enumeration<URL> urls = classLoader != null?classLoader.getResources("META-INF/spring.factories"):ClassLoader.getSystemResources("META-INF/spring.factories");
            ArrayList result = new ArrayList();

            //遍历所有的spring.factories获取给定的factoryClassName(key)
            while(urls.hasMoreElements()) {
                URL url = (URL)urls.nextElement();
                Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
                //获取factoryClassName下配置的值
                String factoryClassNames = properties.getProperty(factoryClassName);
               
               //将factoryClassName下配置的值分割获取集合
               result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
            }

            return result;
        } catch (IOException var8) {
            throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8);
        }
    }

可以看到loadFactoryNames主要完成了spring.factories的查找加载以及对spring.factories的解析等操作,获取到扩展实现的集合后通过反射可以快速的拿到类的实现实例,instantiateFactory方法完成了反射获取实现的过程,不详细分析。

相关文章

网友评论

      本文标题:spring-类SPI机制-SpringFactoriesLoa

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