1. 程式人生 > >SpringBoot自動配置原理原始碼級別分析

SpringBoot自動配置原理原始碼級別分析

# SpringBoot自動配置原理 ### 前言 後面還會講到SpringBoot自動配置原理,會主要講解@EnableAutoConfiguratuon註解幫助我們做了什麼事情,是如何自動把自動配置類掃描到容器中的,建議看完這篇後,兩篇配合使用,[傳送門](https://blog.csdn.net/csdn18740599042/article/details/109028017 "傳送門") ```java package com.staticzz.springboot_quick; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** **@SpringBootApplication註解為核心註解 ** **/ @SpringBootApplication public class SpringbootQuickApplication { public static void main(String[] args) { SpringApplication.run(SpringbootQuickApplication.class, args); } } ``` ###SpringBootApplication註解作用 @SpringBootApplication 標註在某一個類上,就說明這個類為SpringBoot應用的主配置類,SpringBoot就應該執行這個類的main方法來啟動Springboot應用 以前我們開發一個SSM專案,需要利用配置檔案進行相關配置,而SpingBoot利用了配置類進行自動配置, 這裡配置類等同於配置檔案,SpringBoot並且開啟了自動配置,以前我們需要手動配置的東西 這裡SpringBoot幫我們進行了自動配置 PS: 自動配置原理也是SpringBoot的精髓所在 ```java package com.staticzz.springboot_quick; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; /** @SpringBootApplication註解標註在某一個類上, 就說明這個類為SpringBoot應用的主程式類 SpringBoot就應該執行這個類的main方法來啟動Springboot應用 **/ @SpringBootApplication public class SpringbootQuickApplication { public static void main(String[] args) { SpringApplication.run(SpringbootQuickApplication.class, args); } } ``` **那@SpringBootApplication 這個註解與自動配置又有什麼關係呢?** 接下來我們Ctrl+左鍵,進入到這個註解中來檢視 @SpringBootApplication 這個註解裡到底配置了什麼?我們先來進入到@SpringBootApplication這個註解中,看看它底層呼叫了什麼註解 動圖演示: ![image](https://img-blog.csdnimg.cn/20200921215131163.gif#pic_center) 我們觀察到 @SpringBootApplication註解 繼承了 @SpringBootConfiguration註解 ,而 @SpringBootConfiguration註解 又繼承了Spring底層的註解 @Configuration註解 , 凡是標註該註解的類都是配置類 那現在也只是知道了 @SpringBootApplication註解 一層一層的實現了Spring底層的 @Configuration註解 ,被標註後稱為配置類!那說了這篇文章講的是SpringBoot的自動配置?配置有了,**自動呢?** ![image](https://img2020.cnblogs.com/blog/2121961/202103/2121961-20210310231753517-679255786.png?) 我沒有騙人哦!確實是有自動配置的!而且SpringBoot也確確實實幫我們做了自動配置 ![image](https://img2020.cnblogs.com/blog/2121961/202103/2121961-20210310232158706-1165447942.png) 先上一張動態演示圖,瞧瞧 ![image](https://img-blog.csdnimg.cn/20200921221345199.gif#pic_center) 第一步 ctrl+右鍵 進入了 @EnableAutoConfiguration 這個註解 ```java @SuppressWarnings("deprecation") @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited /** **這個註解為自動導包的註解 **/ @AutoConfigurationPackage /** **這個為開啟自動配置選擇器的註解 **/ @Import(EnableAutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; /** * Exclude specific auto-configuration classes such that they will never be applied. * @return the classes to exclude */ Class[] exclude() default {}; /** * Exclude specific auto-configuration class names such that they will never be * applied. * @return the class names to exclude * @since 1.3.0 */ String[] excludeName() default {}; } ``` 有沒有發現我在這動態演示中,重點高亮了兩個註解 **@AutoConfigurationPackage @Import(EnableAutoConfigurationImportSelector.class)** 這兩個註解分別是什麼意思 廢話不多說 下面看! @AutoConfigurationPackage 自動掃描包 @Import(EnableAutoConfigurationImportSelector.class) 匯入自動配置類選擇器元件 來看原始碼分析 @AutoConfigurationPackage 原始碼展示: ```java /** * {@link ImportBeanDefinitionRegistrar} to store the base package from the importing * configuration. */ @Order(Ordered.HIGHEST_PRECEDENCE) static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports { //這個方法為SpringBoot幫助我們自動掃描包獲取獲取包名並進行註冊 @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { register(registry, new PackageImport(metadata).getPackageName()); } @Override public Set determineImports(AnnotationMetadata metadata) { return Collections.singleton(new PackageImport(metadata)); } } ``` 動態展示 自動掃描包 注意觀察動圖中我高亮的部分 ![image](https://img-blog.csdnimg.cn/20200921230903674.gif#pic_center) **結論:SpringBoot在啟動時,會自動掃描主程式類所在的包下的所有子包** 來看原始碼分析 @Import(EnableAutoConfigurationImportSelector.class) ```java @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { if (!isEnabled(annotationMetadata)) { return NO_IMPORTS; } try { AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader .loadMetadata(this.beanClassLoader); //獲取到註解元資料 AnnotationAttributes attributes = getAttributes(annotationMetadata); //獲取到配置類封裝為一個list資料 List configurations = getCandidateConfigurations(annotationMetadata, attributes); configurations = removeDuplicates(configurations); configurations = sort(configurations, autoConfigurationMetadata); Set exclusions = getExclusions(annotationMetadata, attributes); checkExcludedClasses(configurations, exclusions); configurations.removeAll(exclusions); configurations = filter(configurations, autoConfigurationMetadata); fireAutoConfigurationImportEvents(configurations, exclusions); //返回給容器 return configurations.toArray(new String[configurations.size()]); } catch (IOException ex) { throw new IllegalStateException(ex); } } ``` @Import(EnableAutoConfigurationImportSelector.class) 這個註解的作用選擇自動配置類並掃描進容器中, 動態展示 匯入自動配置類選擇器元件 ![image](https://img-blog.csdnimg.cn/20200921234328863.gif#pic_center) ###總結: SpringBoot給容器中匯入非常多的自動配置類(xxxAutoConfiguration),就是給容器中匯入場景所需要的所有元件並自動配置好這些