springboot原始碼解析-管中窺豹系列之自動裝配(九)
阿新 • • 發佈:2021-03-02
# 一、前言
- Springboot原始碼解析是一件大工程,逐行逐句的去研究程式碼,會很枯燥,也不容易堅持下去。
- 我們不追求大而全,而是試著每次去研究一個小知識點,最終聚沙成塔,這就是我們的springboot原始碼管中窺豹系列。
![ 簡介 ](https://zhangbin1989.gitee.io/blog/picture/zb0018_springsour/springboot_source_0.png)
# 二、何為自動裝配?
- 我們想用redis,直接引入spring-boot-starter-data-redis的依賴,配置加上就能用。
- 我們想用mongodb, 直接引入mongodb的依賴
- 我們想用快取,直接引入cache的依賴
- 我們在:springboot原始碼解析-管中窺豹系列之web伺服器(七) 裡面想更換不同的web伺服器,更換不同的依賴,那裡也是用到自動裝配
# 三、原始碼分析
我們從main方法所在類開始看:
```
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyprojectApplication {
public static void main(String[] args) {
SpringApplication.run(MyprojectApplication.class, args);
}
}
```
這次不進main方法,我們看註解:@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 {
...
}
```
- 我們看這個註解:@EnableAutoConfiguration
- 注意這個註解是在:spring-boot-autoconifgure依賴包裡面
```
@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 {};
}
```
- spring.boot.enableautoconfiguration:自動裝配的開關,預設開
- 我們看這個:@Import(AutoConfigurationImportSelector.class)
- springboot會載入@Import 和 繼承ImportSelector的類 到bean集合裡面
```
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
...
}
```
- 繼承的各種Aware,我們之前說過:springboot原始碼解析-管中窺豹系列之aware(六)
- Ordered:我們在之前排序那一節也說過:springboot原始碼解析-管中窺豹系列之排序(五)
- ImportSelector是把繼承的selectImports方法的返回陣列轉換成載入的bean
```
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
....
private static final String[] NO_IMPORTS = {};
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected boolean isEnabled(AnnotationMetadata metadata) {
if (getClass() == AutoConfigurationImportSelector.class) {
return getEnvironment().getProperty(EnableAutoConfiguration.ENABLED_OVERRIDE_PROPERTY, Boolean.class, true);
}
return true;
}
....
}
```
- 先判斷開關,沒開啟就返回空陣列
- getAutoConfigurationEntry() 拿到要載入成bean的物件
- 轉換成陣列返回
- 我們看看這個方法:getAutoConfigurationEntry()
```
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);