1、自動配置原理
@SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { }
可以看到有注解@EnableAutoConfiguration
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
可以看到
@Import(AutoConfigurationImportSelector.class)
@Import可以導入向spring中導入組件 ,可以看下鏈接的文檔
接着看下AutoConfigurationImportSelector.selectImports()方法,
selectImports方法調用是在前面的refresh方法的invokeBeanFactoryPostProcessors中,感興趣的可以看下spring 源碼解析一(bean定義)
@Override public String[] selectImports(AnnotationMetadata annotationMetadata) { //如果AutoConfiguration沒開,返回 if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } //將spring-autoconfigure-metadata.properties的鍵值對配置載入到PropertiesAutoConfigurationMetadata對象中並返回 AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader .loadMetadata(this.beanClassLoader); //獲取@EnableAutoConfiguration 注解的屬性 AnnotationAttributes attributes = getAttributes(annotationMetadata); //從META-INF/spring.factories文件中獲取EnableAutoConfiguration所對應的configurations List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); // 去重,List轉Set再轉List configurations = removeDuplicates(configurations); // 從注解的exclude/excludeName屬性中獲取排除項 Set<String> exclusions = getExclusions(annotationMetadata, attributes); // 對於不屬於AutoConfiguration的exclude報錯 checkExcludedClasses(configurations, exclusions); // 從configurations去除exclusions configurations.removeAll(exclusions); // 應用過濾器AutoConfigurationImportFilter, // 此過濾器檢查候選配置類上的注解如@ConditionalOnClass,如果要求的類在classpath 中不存在,則這個候選配置類會被排除掉 configurations = filter(configurations, autoConfigurationMetadata); // 現在已經找到所有需要被應用的候選配置類 // 廣播事件 AutoConfigurationImportEvent fireAutoConfigurationImportEvents(configurations, exclusions); return StringUtils.toStringArray(configurations); }
這部分代碼比較簡單,就是讀取META-INF/spring.factories文件,然后過濾EnableAutoConfiguration注解上的exclude,然后再根據去重,再根據@ConditionalOnClass匹配過濾
在spring.factories中可以發現redis,mq,jdbc等等自動啟動器,但是卻沒有發現mybatis的
其實也是,mybatis的包都是手動maven導進來的,可以看下mybatis的自動啟動器是怎么實現的
有兩個包,一個是mybatis-spring-boot-starter,一個是mybatis-spring-boot-autoconfigure,starter里什么都沒有,就是添加了mybatis-spring-boot-autoconfigure的pom文件
可以發現autoconfigure下面也有一個spring.factories文件,里面有個MybatisAutoConfiguration,mybatis自己實現了自啟動功能
所以我們如果自己需要實現自動啟動器,也可以模仿mybatis實現一個,將實現的AutoConfiguration放到spring.factories文件里。