為什麼 Spring Boot 不用配置,也能運作相關元件?
@SpringBootApplication --> @EnableAutoConfiguration -> @Import({AutoConfigurationImportSelector.class}) ,我們一步一步往下走:
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(
autoConfigurationMetadata, annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
然後selectImports --> getAutoConfigurationEntry --> getCandidateConfigurations
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
然後一層層的跟蹤,在 getCandidateConfigurations 中,是 spring先生産再配置資訊。getSpringFactoriesLoaderFactoryClass 方法傳回了EnableAutoConfiguration.class。
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
loadFactoryNames 方法調用 loadSpringFactories 方法,首先加載了 META-INF/spring.factories 配置檔案,再整合到一起傳回,調用了 map 的 getOrDefault 這兩個方法, 根據 key 擷取一個list。key是通過 getSpringFactoriesLoaderFactoryClass 方法擷取的 EnableAutoConfiguration.class 的全路徑名: org.springframework.boot.autoconfigure.EnableAutoConfiguration。
在 spring-boot 和spring-boot-autoconfigure中找到META-INF/spring.factories,,在 spring-boot-autoconfigure 的配置檔案中找到 org.springframework.boot.autoconfigure.EnableAutoConfiguration。這裡的類就是自動配置的類。
總結 Spring Boot 做了些什麼:
通過注解: @SpringBootApplication --> @EnableAutoConfiguration -> @Import({AutoConfigurationImportSelector.class}) ,最終引入了 AutoConfigurationImportSelector 這個類,加載了 META-INF/spring.factories 檔案,傳回了 org.springframework.boot.autoconfigure.EnableAutoConfiguration 配置的資訊(類)。
以 WebMvcAutoConfiguration 自動配置類為例子,了解這些自動配置類做了些什麼:
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
- @ Configuration,表明這個是一個配置資訊的類,就是相當于老版本的 xml 配置方式;
- @Conditional,這些是用于判斷是否自動配置;
- after 是配置完畢之後進行的,像配置 DispatcherServletAutoConfiguration,這個是 mvc 的,都執行完畢之後,再調用 ValidationAutoConfiguration 對它進行驗證。
-
在類主體中,有 @ConditionalOnProperty 注解,表明我們可以在配置檔案中指定相應的值,然後自動配置類就通過這些配置去做出相應的反應,像加載相應功能等等。
總結:
- Spring Boot 架構不是重複的無用功,這些自動配置類都可以了解為對其他架構的整合。
-
通過注解 @SpringBootApplication --> @EnableAutoConfiguration -> @Import({AutoConfigurationImportSelector.class}) ,再從 META-INF/spring.factories 配置檔案中傳回自動配置類。
Tips:
- 配置類可以配置哪些資訊,在對應的 ***Properties類中有聲明。
- 可以設定 debug = true生成自動配置報告,可以顯示自動配置的資訊。