在pom文件中java
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
在它的父工程中,有他的核心依賴web
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.2.1.RELEASE</version> <relativePath>../../spring-boot-dependencies</relativePath> </parent>
點進去,咱們發現,springboot自動幫咱們管理了依賴spring
這只是其中的一小部分,咱們在寫或者引入有一些依賴的時候,不須要指定版本springboot
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
springboot-boot-starter:就是spring-boot的場景啓動器app
這裏的 spring-boot-starter-web 幫咱們導入了web模塊正常運行所依賴的組件;spring-boot
SpringBoot將全部的功能場景都抽取出來,作成一個個的starter (啓動器),只須要在項目中引入這些starter便可,全部相關的依賴都會導入進來 , 咱們要用什麼功能就導入什麼樣的場景啓動器便可 ;spa
package com.bao; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class Springboot01HelloworldApplication { public static void main(String[] args) { SpringApplication.run(Springboot01HelloworldApplication.class, args); } }
@SpringBootApplication 來標註一個主程序類 , 說明這是一個Spring Boot應用命令行
run方法: 將Spring應用啓動起來code
咱們看一下@SpringBootApplication
註解xml
//四個標準註解 @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 { ......略 }
- @SpringBootConfiguration :SpringBoot的配置類 ,標註在某個類上,表示這是一個SpringBoot的配置類
- @EnableAutoConfiguration : 啓用自動配置,這個註解是讓Spring Boot配置可以如此簡化的關鍵性註解
- @ComponentScan : 掃描當前主啓動類同級的包
點擊@SpringBootConfiguration
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration public @interface SpringBootConfiguration { @AliasFor(annotation = Configuration.class) boolean proxyBeanMethods() default true; }
@Configuration : 表明是一個spring配置類
點擊
Configuration
發現有一個@Component,表明是一個spring組件
點擊@EnableAutoConfiguration
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.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(AutoConfigurationImportSelector.class)兩個
AutoConfigurationPackage(自動配置包)
註解的做用是將 添加該註解的類所在的package 做爲 自動配置package 進行管理。
主要是Registrar.class
package org.springframework.boot.autoconfigure; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.context.annotation.Import; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited //導入選擇器 @Import(AutoConfigurationPackages(自動配置註冊包).Registrar.class) public @interface AutoConfigurationPackage { }
@import :Spring底層註解@import , 給容器中導入一個組件 ,導入的組件由 {Registrar.class} 將主配置類 【即@SpringBootApplication標註的類】的所在包及包下面全部子包裏面的全部組件掃描到Spring容器 ;
@Import(AutoConfigurationImportSelector.class)
它將全部須要導入的組件以全類名的方式返回 , 這些組件就會被添加到容器中 ;
它會給容器中導入很是多的自動配置類 (xxxAutoConfiguration), 就是給容器中導入這個場景須要的全部組件 , 並配置好這些組件 ;
有了自動配置類 , 免去了咱們手動編寫配置注入功能組件等的工做;
點擊AutoConfigurationImportSelector
有這樣的一個方法
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:獲取候選配置
//獲取全部配置 List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
點擊getCandidateConfigurations
裏面的方法
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader()); //斷言非空 Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you " + "are using a custom packaging, make sure that file is correct."); return configurations; }
//返回用來加載配置候選的類。標註了EnableAutoConfiguration註解的類(主啓動類) protected Class<?> getSpringFactoriesLoaderFactoryClass() { return EnableAutoConfiguration.class; }
而在
@SpringBootApplication
註解中標註了@EnableAutoConfiguration因此就是啓動類下的全部資源被導入
在這裏咱們發現了META-INF/spring.factories文件.這個就是自動配置的核心文件
咱們去springboot的jar中尋找該文件
List<String> configurations = SpringFactoriesLoader.loadFactoryNames (getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());
點擊loadFactoryNames
方法
loadFactoryNames : 獲取全部的加載配置
返回的loadSpringFactories
從這些資源中便利了全部的nextElement元素(也能夠理解爲自動配置)
遍歷完成後封裝成Properties,供咱們使用
//全部資源加載到配置類中 Properties properties = PropertiesLoaderUtils.loadProperties(resource);
獲取項目資源:classLoader.getResources(FACTORIES_RESOURCE_LOCATION) 獲取系統資源:ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION))
點擊FACTORIES_RESOURCE_LOCATION
,獲取靜態資源的位置
從META-INF/spring.factories獲取配置文件
須要導入對應的starter才能起做用
例如
因爲@ConditionalOnClass
的存在,會判斷條件成立,纔會加載配置這個類
@ConditionalOnXXX
若是這裏面的條件都知足,纔會生效
SpringBoot全部的自動配置都在啓動類中掃描並加載,也就是spring.factories
文件
全部的自動配置類都在這個文件中,可是並不必定生效,要判斷條件是否成立,只要導入對應的start,就會有對應的啓動器,有了啓動器,自動裝配就會生效,而後就配置成功了
1.springboot在啓動的時候,會從類路徑下META-INF/spring.factories
文件中獲取指定的值
2.將這些自動配置的類導入容器,自動配置類就會生效,幫咱們進行自動配置
3.springboot幫咱們作了咱們之前須要的配置.
4.整個J2EE的總體解決方案和自動配置都在springboot-autoconfigure的jar包中;
5.他會把全部須要導入的組件,以類名的方式返回,這些組件就會被添加到容器
6.容器中也會存在很是多的XxxAutoConfiguration的文件(@Bean),就是這些類給容器中導入了這個場景所須要的全部組件
7.有了自動配置類,就不須要寫配置文件
咱們找一個打開看看 : WebMvcAutoConfiguration
因此,真正實現是從classpath中搜尋全部的META-INF/spring.factories配置文件 ,並將其中對應的 org.springframework.boot.autoconfigure. 包下的配置項經過反射實例化爲對應標註了 @Configuration的JavaConfig形式的IOC容器配置類 , 而後將這些都彙總成爲一個實例並加載到IOC容器中。
@SpringBootApplication public class SpringbootDemo02Application { public static void main(String[] args) { //該方法返回一個ConfigurableApplicationContext對象 //參數一:應用入口的類 參數類:命令行參數 SpringApplication.run(SpringbootDemo02Application.class, args); } }
分析該方法主要分兩部分,一部分是SpringApplication的實例化,二是run方法的執行;
1.推斷應用的類型是普通的項目仍是Web項目
2.查找並加載全部可用初始化器 , 設置到initializers屬性中
3.找出全部的應用程序監聽器,設置到listeners屬性中
4.推斷並設置main方法的定義類,找到運行的主類