@AutoConfiguration读取所有jar包下的 /META-INF/spring.factories
并追加到一个 LinkedMultiValueMap
中 。每一个url中记录的文件路径如下:
file:/C:/Users/wangchao/apache-maven-3.5.0/repo/com/baomidou/mybatis-plus-boot-starter/3.5.1/mybatis-plus-boot-starter-3.5.1.jar!/META-INF/spring.factories按照如下路径查看
// 1. @EnableAutoConfiguration@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inherited@AutoConfigurationPackage@Import(AutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration {}// 2. AutoConfigurationImportSelector.class#selectImports()public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered { @Override public String[] selectImports(AnnotationMetadata annotationMetadata) {if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); }}// 3. AutoConfigurationImportSelector.class#getAutoConfigurationEntry()protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) {return EMPTY_ENTRY; } AnnotationAttributes attributes = getAttributes(annotationMetadata); List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); configurations = removeDuplicates(configurations); Set<String> exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = getConfigurationClassFilter().filter(configurations); fireAutoConfigurationImportEvents(configurations, exclusions); return new AutoConfigurationEntry(configurations, exclusions);}// 4. AutoConfigurationImportSelector.class#getCandidateConfigurations()protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(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;}// 5. org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames()public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) { String factoryTypeName = factoryType.getName(); return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());}
最终使用 loadSpringFactories(@Nullable ClassLoader classLoader)
方法读取所有配置文件 。// 6. org.springframework.core.io.support.SpringFactoriesLoader#loadSpringFactories()private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {MultiValueMap<String, String> result = cache.get(classLoader);if (result != null) {return result;}try {Enumeration<URL> urls = (classLoader != null ?classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));result = new LinkedMultiValueMap<>();while (urls.hasMoreElements()) {// 读取所有jar包下的 /META-INF/spring.factoriesURL url = urls.nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils.loadProperties(resource);for (Map.Entry<?, ?> entry : properties.entrySet()) {String factoryTypeName = ((String) entry.getKey()).trim();for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {result.add(factoryTypeName, factoryImplementationName.trim());}}}cache.put(classLoader, result);return result;}catch (IOException ex) {throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_RESOURCE_LOCATION + "]", ex);} }
tomcat的自动配置内置于springboot的autoconfiguration中 。参考tomcat的自动配置 https://www.cnblogs.com/zhaokejin/p/15626392.htmlmybatis-plus的配置没有被springboot包括 。因此mybatis-stater中包含一个包
mybatis-spring-boot-autoconfigure
,这其中配置了需要自动配置的类 。因此我们也可以在自己的项目下新建
/META-INF/spring.factories
,并配置自动配置类 。@Import【SpringBoot 常用注解的原理和使用】@Import 用于导入配置类或需要前置加载的类 。被导入的类会注册为Bean,可直接作为Bean被引用 。它的 value 属性可以支持三种类型:
- 被
@Configuration
修饰的配置类、或普通类(4.2版本之后可以) 。 ImportSelector
接口的实现 。推荐阅读
- 弹性分布式数据集 RDD及常用算子
- pytorch、paddlepaddle等环境搭建 深度学习环境搭建常用网址、conda/pip命令行整理
- 之六 2流高手速成记:从SpringBoot到SpringCloudAlibaba
- 三十九 Java开发学习----SpringBoot整合mybatis
- SpringBoot 阶段测试 1
- 三 SpringBoot - Ribbon客户端负载均衡,Zuul网关,Config配置中心
- 之五 2流高手速成记:Springboot整合Shiro实现安全管理
- SpringBoot Starter缘起
- SpringBoot自定义注解+异步+观察者模式实现业务日志保存
- 装配 SpringBoot自动配置流程