一、理解 spring-boot-starter 自動裝配
大家都知道使用 spring-boot-starter 可以簡化日常開放中的配置,那麼大家是否好奇,這些簡化的配置SpringBoot是怎麼爲我們的應用自動裝配的呢?帶着疑問,一起來看看SpringBoot的自動裝配功能吧。
- 理解 @SpringBootApplication 啓動類註解
1.1 @SpringBootApplication 由以下三個關鍵註解組成
@SpringBootConfiguration // 該註解與 @Configuration 無異
@ComponentScan // 該註解用於激活註解掃描
@EnableAutoConfiguration // 該註解用於激活自動裝配
@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註解中使用 @Import({AutoConfigurationImportSelector.class}) ,導入了AutoConfigurationImportSelector類。
由於AutoConfigurationImportSelector 是 ImportSelector 接口的子類,所以直接看 AutoConfigurationImportSelector#selectImports() ,如下:
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@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());
}
}
繼續往下看 getAutoConfigurationEntry 方法是如何實現的
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
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 = filter(configurations, autoConfigurationMetadata);
// 發佈自動裝配事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
獲取準備裝配的配置類集合 getCandidateConfigurations() 方法實現
大家可以看到,重點是獲取準備裝配的配置類集合方法 getCandidateConfigurations() 進一步往下看會看到,程序會去加載根目錄下的 META-INF/spring.factories 文件,META-INF/spring.factories 如下所示:
可以看到 META-INF/spring.factories 是一個properties文件,其中
org.springframework.boot.autoconfigure.EnableAutoConfiguration
對應的value則是SpringBoot自動裝配的配置類,包括我們常見的數據庫自動裝配 DataSourceAutoConfiguration和RedisAutoConfiguration自動裝配等。這樣就可以做到我們在application.properties文件中只需配置數據庫與redis的連接信息就可以使用了。
二、自定義開發 spring-boot-starter
1、新建項目customer-spring-boot-starter
- 添加一個 CustomerAutoConfiguration 配置類,並註冊一個 String 類型的bean
- 在根目錄下新建 /META-INF/spring.factories文件,並配置上一步的新增的配置類 CustomerAutoConfiguration
2、新建一個測試項目 test 並在pom文件中引用 customer-spring-boot-starter
可以看到控制檯輸入的張三,就是我們自動裝配的bean,自定義開發Spring-boot-starter就是這麼簡單 !
源碼地址:https://github.com/yuhuangbin/spring-boot-starter-sample