SpringBoot自動裝配解析
@SpringBootApplication 其實是一個組合註解 點進去可以看到三個比較重要的註解為SpringBootConfiguration、EnableAutoConfiguration、ComponentScan
@SpringBootConfiguration //標明是一個配置類 @EnableAutoConfiguration //開啟自動配置 @ComponentScan( //掃描啟動類所在的包 excludeFilters = {@ComponentScan.Filter( type= FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @ComponentScan.Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} )
@EnableAutoConfiguration也是一個派生註解,其中的關鍵功能由@Import提供 其匯入的AutoConfigurationImportSelector的selectImports()方法通過SpringFactoriesLoader.loadFactoryNames()掃描所有具有META-INF/spring.factories的jar包。spring-boot-autoconfigure-x.x.x.x.jar裡就有一個這樣的spring.factories檔案。
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import({AutoConfigurationImportSelector.class})//這一步是關鍵通過@Import註解將AutoConfigurationImportSelector注入到ioc容器中 public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY= "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
這個@EnableAutoConfiguration註解通過@SpringBootApplication被間接的標記在了Spring Boot的啟動類上。在SpringApplication.run(...)的內部就會執行selectImports()方法,找到所有JavaConfig自動配置類的全限定名對應的class,然後將所有自動配置類載入到Spring容器中。通過類跟蹤可以看到最終呼叫方法如下
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) { MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader); if (result != null) { return result; } else { try { Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); LinkedMultiValueMap result = new LinkedMultiValueMap(); while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator(); while(var6.hasNext()) { Entry<?, ?> entry = (Entry)var6.next(); String factoryClassName = ((String)entry.getKey()).trim(); String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); int var10 = var9.length; for(int var11 = 0; var11 < var10; ++var11) { String factoryName = var9[var11]; result.add(factoryClassName, factoryName.trim()); } } } cache.put(classLoader, result); return result; } catch (IOException var13) { throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13); } } }
簡述:
自動裝配就是根據EnableAutoConfiguration註解載入meta-info/spring.factories配置檔案中所有自動配置類,並對其進行載入。而這些自動配置類都是以AutoConfiguration結尾來命名的,它實際上就是一個JavaConfig形式的Spring容器配置類,它能通過以Properties結尾命名的類中取得在全域性配置檔案中配置的屬性如:server.port,而XxxxProperties類是通過@ConfigurationProperties註解與全域性配置檔案中對應的屬性進行繫結的。