1. 程式人生 > >springboot原始碼解析-管中窺豹系列之自動裝配(九)

springboot原始碼解析-管中窺豹系列之自動裝配(九)

# 一、前言 - 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);