自动配置原理
-
@SpringBootApplication springboot应用程序入口
-
@SpringBootConfiguration
声明此注解为springboot配置文件
-
@EnableAutoConfiguration
自动配置注解
-
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })对包进行扫描,把组件加入容器中
-
-
@EnableAutoConfiguration
-
@Import(AutoConfigurationImportSelector.class)
-
AutoConfigurationImportSelector.class
-
selectImports方法
@Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); }
-
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); }
-
getCandidateConfigurations 获取候选的配置
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { //获取到全部的配置类,也就是value值 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; }
-
-
-
-
loadFactoryNames
public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) { ClassLoader classLoaderToUse = classLoader; if (classLoaderToUse == null) { classLoaderToUse = SpringFactoriesLoader.class.getClassLoader(); } String factoryTypeName = factoryType.getName(); return loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList()); }
-
loadSpringFactories
private static Map<String, List<String>> loadSpringFactories(ClassLoader classLoader) { Map<String, List<String>> result = cache.get(classLoader); if (result != null) { return result; } result = new HashMap<>(); try { Enumeration<URL> urls = classLoader.getResources(FACTORIES_RESOURCE_LOCATION); while (urls.hasMoreElements()) { URL url = urls.nextElement(); UrlResource resource = new UrlResource(url); //获取对于路径下的全部资源 key-value形式,此时value可有多个值 META-INF/spring.factories Properties properties = PropertiesLoaderUtils.loadProperties(resource); //将value放入到List result的key还是原来的key值,result的value为存放资源value的List for (Map.Entry<?, ?> entry : properties.entrySet()) { String factoryTypeName = ((String) entry.getKey()).trim(); String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String) entry.getValue()); for (String factoryImplementationName : factoryImplementationNames) { result.computeIfAbsent(factoryTypeName, key -> new ArrayList<>()) .add(factoryImplementationName.trim()); } } } // Replace all lists with unmodifiable lists containing unique elements result.replaceAll((factoryType, implementations) -> implementations.stream().distinct() .collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList))); cache.put(classLoader, result); } catch (IOException ex) { throw new IllegalArgumentException("Unable to load factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex); } return result; }
-
FACTORIES_RESOURCE_LOCATION
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
-
自动配置失效
-
扫描@ConditionalXXX注解来判断是否放弃使用已有的配置而使用配置文件的配置
@Conditional扩展注解 作用(判断当前条件是否满足) @ConditionalOnJava 系统的java版本是否符合要求 @ConditionalOnBean 容器中是否存在指定的Bean @ConditionalOnMissingBean 容器中不存在指定的类 @ConditionalOnExpression 满足SpEL表达式指定规范 @ConditionalOnClass 在系统中有指定的对应的类 @ConditionalOnMissingClass 在系统中没有指定对应的类 @ConditionalOnSingleCandidate 容器中是否指定一个单实例的Bean,或者找个是一个首选的Bean @ConditionalOnProperty 系统中指定的对应的属性是否有对应的值 @ConditionalOnResource 类路径下是否存在指定的资源文件 @ConditionalOnWebApplication 当前是Web环境 @ConditionalOnNotWebApplication 当前不是Web环境 @ConditionalOnJndi JNDI存在指定项 @Bean @ConditionalOnMissingBean(HiddenHttpMethodFilter.class) @ConditionalOnProperty(prefix = "spring.mvc.hiddenmethod.filter", name = "enabled") public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() { return new OrderedHiddenHttpMethodFilter(); } @Bean @ConditionalOnMissingBean(FormContentFilter.class) //在系统配置文件(application.yml)中是否有配置spring.mvc.formcontent.filter,如果有,将不会执行下面的配置,而使用系统配置文件中的配置 @ConditionalOnProperty(prefix = "spring.mvc.formcontent.filter", name = "enabled", matchIfMissing = true) public OrderedFormContentFilter formContentFilter() { return new OrderedFormContentFilter(); }
-