SpringBoot的starter到底是什么?( 五 )

門面模式,其他業務系統想引入相應的功能,必須要通過這個門面 。
我們重點分析一下 id-generate-autoconfiguration.jar
該jar包核心內容是:IdGenerateConfiguration,這個配置類中創建了IdGenerateService對象 , IdGenerateService是我們所需要自動配置的具體功能 。
接下來一個最重要的問題:IdGenerateConfiguration為什么會自動加載的呢?
還記得我們定義的spring.factories文件不?
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.sue.IdGenerateAutoConfiguration它里面只包含一行配置,其中keyEnableAutoConfiguration,valueIdGenerateAutoConfiguration
要搞明白這個過程,要從Application類的@SpringBootApplication注解開始:
@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 {@AliasFor(annotation = EnableAutoConfiguration.class)Class<?>[] exclude() default {};@AliasFor(annotation = EnableAutoConfiguration.class)String[] excludeName() default {};@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")String[] scanBasePackages() default {};@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")Class<?>[] scanBasePackageClasses() default {};}從上面可以看出該注解里面包含了@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 {};}@EnableAutoConfiguration注解會引入AutoConfigurationImportSelector類 。
該類的selectImports方法一個關鍵方法:
@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {//配置有沒有配置spring.boot.enableautoconfiguration開關 , 默認為true//如果為false,則不執行自動配置的功能,直接返回if (!isEnabled(annotationMetadata)) {return NO_IMPORTS;}//找spring-autoconfigure-metadata.properties中的元素AutoConfigurationMetadata autoConfigurationMetadata = https://www.huyubaike.com/biancheng/AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);//獲取EnableAutoConfiguration注解中的屬性AnnotationAttributes attributes = getAttributes(annotationMetadata);//獲取工程下所有配置key為EnableAutoConfiguration的值,即IdGenerateConfiguration等類 。List configurations = getCandidateConfigurations(annotationMetadata,attributes);//刪除重復的值configurations = removeDuplicates(configurations);//獲取需要排除的規則列表Set exclusions = getExclusions(annotationMetadata, attributes);//檢查checkExcludedClasses(configurations, exclusions);//刪除需要排除的值configurations.removeAll(exclusions);//根據配置文件中配置的開關 , 過濾一部分不滿足條件的值configurations = filter(configurations, autoConfigurationMetadata);fireAutoConfigurationImportEvents(configurations, exclusions);return StringUtils.toStringArray(configurations);}這里就是starter能夠自動配置的秘密
此外,有些朋友看其他人定義的springboot starter可能會有疑惑 。
先看看druid-spring-boot-starter

SpringBoot的starter到底是什么?

文章插圖
alibaba定義的druid-spring-boot-starter只有xxx-spring-boot-starter.jar文件,而沒有xxx-spring-boot-autoconfigure.jar文件 。
再看看spring-boot-starter-jdbc
SpringBoot的starter到底是什么?

文章插圖
更神奇的是這個文件中連pom.xml都沒有 , 一臉懵逼 。。。。。。。
是不是我講錯了?
答:其實沒有 。
SpringBoot的原則是約定優于配置 。
從spring-boot-starter-jdbc內部空實現來看,它的約定是要把xxx-spring-boot-starter.jar和xxx-spring-boot-autoconfigure.jar區分開的 。個人認為,alibaba定義得并不好 , 沒有遵照springboot的約定,雖然功能不受影響 。(這個地方歡迎一起探討一下)
而springboot自己定義的spring-boot-starter-jdbc為什么連pom.xml文件也沒有呢?
它不需要依賴xxx-spring-boot-autoconfigure.jar文件嗎?
因為springboot把所有的自動配置的類都統一放到spring-boot-autoconfigure.jar下面了:

推薦閱讀