AutoConfiguration加载元数据和自动配置组件( 二 )


AutoConfiguration加载元数据和自动配置组件文章插图
@EnableAutoConfiguration 加载自动配置 组件加载自动配置组件是自动配置的核心组件之一 , 这些自动配置组件在类路径中 METAINF 目录下的 Ssping fctories 文件中进行注册 。 Spring Boof 预置了-部分常用组件 , 如果我们需要创建自己的组件 , 可参考 SpringBoot 预置组件在自己的 Starters 中进行配置 , 在后面的章节中会专门对此进行讲解 。
通过 Sping Core 提供的 Soingacaorestoaodar 类可以读取 spring. fctories 文件中注册的类 。 下面我们通过源代码来看一下如何在 AutoConfigurationlmportSelector 类中通过 getCateConfigurations 方法来读取 spring.factories 文件中注册的类 。
protected List getCandidateConfigurat ions (Annotat ionMetadata metadata,AnnotationAttributes attributes) {List configurations = SpringFactoriesLoader . loadF actoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());Assert. notEmpty (configurations ,"No auto configuration classes found in META-INF/spring.factories. If you+ "are using a custom packaging, make sure that file is Correct.");return configurations;protected Class getSpringF actoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;}getCandidateConfigurations 方 法 使 用 SpringFactoriesL oader 类 提 供 的loadFactoryNames 方法来读取 META-INF/spring.factories 中的配置 。 如果程序未读取到任何 配 置 内 容,会 抛 出 异 常 信 息。而 loadFactoryNames 方 法 的 第 一 个 参 数 为getSpringFactoriesL oaderFactoryClass 方法返回的 EnableAutoConfiguration.class , 也就是说 loadFactoryNames 只会读取配置文件中针对自动配置的注册类 。
SpringFactoriesLoader 类的 loadFactoryNames 方法相关代码如下 。
public final class SpringFactoriesLoader {//概类加载文件的路径 ,可能存在多个public static final String FACTORIES_ RESOURCE LOCATION = "META- INF/spring. factories";//加载所有的 META- INF/spring. factories.文件 , 封装成 Map, 并从中获取指定类名的列表public static List loadFactoryNames(Class factoryClass, @Nullable ClassLoader classLoader) {String factoryClassName = factoryClass . getName();return loadSpringFactories (classLoader) . getOrDefault(factoryClassName ,Collections . emptylist());//加载所有的 META- INF/spring. factories 文件 , 封装成 Map ,Key 为接口的全类名 , Value 为对应配置值的 ist 集合private static Map> loadSpringFactories (@Nullable ClassLoader classLoader) {MultiValueMap result = cache.get(classLoader);if (result != null) {return result;try {Enumeration urls = (classLoader != null ?classLoader . getResources(FACTORIES_ RESOURCE_ LOCATION) :ClassLoader . getSystemResources (FACTORIES_ RESOURCE_ LOCATION));result = new LinkedMultiValueMap<>();while (urls .hasMoreElements()) {URL url = urls .nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils . loadProperties ( resource);for (Map.Entry entry : properties .entrySet()) {String factoryClassName = ((String) entry . getKey()).trim();for (String factoryName : StringUtils . commaDelimitedL istTo-StringArray((String) entry.getValue())) {result . add(factoryClassName, factoryName . trim());cache. put(classLoader, result);return result;} catch (I0Exception ex)throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_ RESOURCE_ _LOCATION + "]" , ex);}} 。。。 }


推荐阅读