Springboot的啓動類能夠是很是簡單,其中最關鍵的兩部分是Annotation定義(@SpringBootApplication
)和類定義(SpringApplication.run),這篇文章主要分析其@SpringBootApplication
註解,後續文章再接着分析其類定義。php
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
複製代碼
其中參考了《SpringBoot揭祕》裏面的分析,也是學習總結了。html
@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 {
.....
}
複製代碼
看似有這麼多註解,實際上@SpringBootApplication
是一個"三體"結構,重要的只有三個Annotation:java
@Configuration
@EnableAutoConfiguration
@ComponentScan
爲何@SpringBootApplication註解
裏沒有包含@Configuration
,其實是在@SpringBootConfiguration
裏面git
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
複製代碼
@SpringBootConfiguration繼承自@Configuration,兩者功能也一致,標註當前類是配置類, 並會將當前類內聲明的一個或多個以@Bean註解標記的方法的實例歸入到spring容器中,而且實例名就是方法名。github
實際上若是咱們使用以下的Springboot啓動類,整個SpringBoot應用依然能夠與以前的啓動類功能對等。web
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
複製代碼
下面分別說說這三個關鍵註解spring
這裏的@Configuration
就是以JavaConfig形式的Spring IoC容器的配置類使用的那個@Configuration
,因此這裏的啓動類標註了@Configuration
以後,自己其實也是一個IoC容器的配置類。數組
之前的XML配置是這樣的:springboot
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" default-lazy-init="true">
<!--bean定義-->
</beans>
複製代碼
如今的JavaConfig配置是這樣的,效果等同,標註了該註解說明就是一個配置類框架
@Configuration
public class Application{
//bean定義
}
複製代碼
更多關於@Configuration
和@Bean
的講解,參考文章: 使用 Java 配置進行 Spring bean 管理
@ComponentScan的功能其實就是自動掃描並加載符合條件的組件或bean定義,最終將這些bean定義加載到容器中。咱們能夠經過basePackages等屬性指定@ComponentScan自動掃描的範圍,若是不指定,則默認Spring框架實現從聲明@ComponentScan所在類的package進行掃描,默認狀況下是不指定的,因此SpringBoot的啓動類最好放在root package下。
各位是否還記得Spring框架提供的各類名字爲@Enable開頭的Annotation定義?好比@EnableScheduling
,@EnableCaching
,@EnableMBeanExport
等,@EnableAutoConfiguration
的理念和"作事方式"其實一脈相承,藉助@Import
的支持,收集和註冊特定場景相關的bean定義:
@EnableScheduling
是經過@Import將Spring調度框架相關的bean定義都加載到Ioc容器中。@EnableMBeanExport
是經過@Import將JMX相關的bean定義加載到Ioc容器而@EnableAutoConfiguration也是藉助@Import的幫助,將全部符合自動配置條件的bean定義加載到Ioc容器,僅此而已
@EnableAutoConfiguration也是一個複合Annotation,其定義以下:
@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 {};
}
複製代碼
其中,最關鍵的要屬@Import(AutoConfigurationImportSelector.class)
,藉助AutoConfigurationImportSelector
這個類,@EnableAutoConfiguration
能夠幫助Springboot應用將全部符合條件的@configuration都加載到當前的SpringBoot建立並使用的Ioc容器
在SpringBoot1.5之前,使用的是EnableAutoConfigurationImportSelector
,它繼承自AutoConfigurationImportSelector
,1.5之後,EnableAutoConfigurationImportSelector
已經再也不被建議使用,而是推薦使用AutoConfigurationImportSelector
。
如今咱們已經知道了在@EnableAutoConfiguration中引入了AutoConfigurationImportSelector類,那麼它是如何被執行的呢?
Springboot啓動時會使用ConfigurationClassParser來解析被@Configuration修飾的配置類,而後再處理這個類內部被其餘註解修飾的狀況,好比@Import註解,@ComponentScan註解,@Bean註解等。
若是發現註解中存在@Import(ImportSelector)的狀況下,就會建立一個相應的importSelector對象,並調用其selectImports方法,而AutoConfigurationImportSelector就是一個ImportSelector的實現類。更多關於ConfigurationClassParser的分析,參閱文章:Spring類註冊筆記
SpringFactoriesLoader的主要功能就是從指定的配置文件META/spring.factories
加載配置,spring.factories是一個典型的java properties文件,配置格式爲Key-Value形式,只不過Key和Value都是Java類型的完整類名。
進入loadFactoryNames()方法,就發現loadFactoryNames()讀取了ClassPath下面的 META-INF/spring.factories 文件。
@SpringBootApplication不只包括上面的三個重要註解,還包含有4個方法:
Class<?>[] exclude() default {};
根據Class來排除特定的類加入Spring容器,傳入參數是class類型String[] excludeName() default {};
根據Class name排除特定的類加入spring容器,傳入參數是class的全類名字符串數組String[] scanBasePackages() default {};
指定掃描包,參數是包名的字符串數組Class<?>[] scanBasePackageClasses() default {};
指定掃描包,參數是Class類型數組這裏總結下@SpringBootApplication中的三個重要註解的特徵:
@Configuration
定義Spring Ioc容器的配置類
@EnableAutoConfiguration
:從classpath中搜尋全部META/spring.factories配置文件,並將其中org.springframework.boot.autoconfigure.EnableAutoConfiguration
對應的配置項,也就是一個自動配置類列表加載到Ioc容器中。 簡單說,就是@EnawebleAutoConfiguration
讓Spring Boot根據類路徑下的jar包依賴爲當前項目進行自動配置,例如,添加了spring-boot-starter-web依賴,會自動添加Tomcat和Spring MVC的依賴。而對於全部標註@Configuration的配置類,統一使用ConfigurationClassParser
解析的。
@ComponentScan
自動掃描並加載符合條件的組件或者bean定義