springboot系列文章之SpringBootApplication註解

前言

Springboot的啓動類能夠是很是簡單,其中最關鍵的兩部分是Annotation定義(@SpringBootApplication)和類定義(SpringApplication.run),這篇文章主要分析其@SpringBootApplication註解,後續文章再接着分析其類定義。php

@SpringBootApplication
public class Application {


    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
複製代碼

其中參考了《SpringBoot揭祕》裏面的分析,也是學習總結了。html

@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 {
    .....
}
複製代碼

看似有這麼多註解,實際上@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

這裏的@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

@ComponentScan的功能其實就是自動掃描並加載符合條件的組件或bean定義,最終將這些bean定義加載到容器中。咱們能夠經過basePackages等屬性指定@ComponentScan自動掃描的範圍,若是不指定,則默認Spring框架實現從聲明@ComponentScan所在類的package進行掃描,默認狀況下是不指定的,因此SpringBoot的啓動類最好放在root package下。

@EnableAutoConfiguration

各位是否還記得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容器

springboot

AutoConfigurationImportSelector

在SpringBoot1.5之前,使用的是EnableAutoConfigurationImportSelector,它繼承自AutoConfigurationImportSelector,1.5之後,EnableAutoConfigurationImportSelector已經再也不被建議使用,而是推薦使用AutoConfigurationImportSelector

什麼時候被執行

如今咱們已經知道了在@EnableAutoConfiguration中引入了AutoConfigurationImportSelector類,那麼它是如何被執行的呢?

Springboot啓動時會使用ConfigurationClassParser來解析被@Configuration修飾的配置類,而後再處理這個類內部被其餘註解修飾的狀況,好比@Import註解,@ComponentScan註解,@Bean註解等。

若是發現註解中存在@Import(ImportSelector)的狀況下,就會建立一個相應的importSelector對象,並調用其selectImports方法,而AutoConfigurationImportSelector就是一個ImportSelector的實現類。更多關於ConfigurationClassParser的分析,參閱文章:Spring類註冊筆記

selector
因此ConfigurationClassParser會實例化一個AutoConfigurationImportSelector 並調用它的 selectImports() 方法
get
在selectImports方法中有使用getCandidateConfigurations()這個方法,這個方法走進去,就能夠看到自動配置的幕後英雄:SpringFactoriesLoader
loader

自動配置的幕後英雄:SpringFactoriesLoader

SpringFactoriesLoader的主要功能就是從指定的配置文件META/spring.factories加載配置,spring.factories是一個典型的java properties文件,配置格式爲Key-Value形式,只不過Key和Value都是Java類型的完整類名。

進入loadFactoryNames()方法,就發現loadFactoryNames()讀取了ClassPath下面的 META-INF/spring.factories 文件。

load
在@EnableAutoConfiguration的場景中,它更可能是提供一種配置查找的功能支持,即根據@EnableAutoConfiguration的完整類名org.springframework.boot.autoconfigure.EnableAutoConfiguration做爲查找的key,獲取對應的一組@Configuration類
auto

SpringBootApplication註解中4個方法

@SpringBootApplication不只包括上面的三個重要註解,還包含有4個方法:

method

  • 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定義

參考資料

相關文章
相關標籤/搜索