1. 程式人生 > >SpringApplication解讀(一):註解

SpringApplication解讀(一):註解

main方法入口:

@SpringBootApplication
public class TestApplication {
	public static void main(String[] args) {
		SpringApplication.run(TestApplication.class, args);
	}
}

點選@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 {
   ......
}

@Retention @Target @Document @Inherited 四個為元註解:

@Retention:定義註解的保留策略。

                       RetentionPolicy.RUNTIME:註解會在class位元組碼檔案中存在,在執行時可以通過反射獲取到

                       RetentionPolicy.CLASS:預設的保留策略,註解會在class位元組碼檔案中存在,但執行時無法獲得

                       RetentionPolicy.SOURCE:註解僅存在於原始碼中,在class位元組碼檔案中不包含

 

@Target :定義註解的作用目標

                   ElementType.TYPE   //介面、類、列舉、註解
                   ElementType.FIELD //欄位、列舉的常量
                   ElementType.METHOD) //方法
                   ElementType.PARAMETER) //方法引數
                   ElementType.CONSTRUCTOR)  //建構函式
                   ElementType.LOCAL_VARIABLE)//區域性變數
                   ElementType.ANNOTATION_TYPE)//註解
                   ElementType.PACKAGE) ///包 

@Document :說明該註解將被包含在javadoc中

@Inherited:說明子類可以繼承父類中的該註解

@Configuration、@EnableAutoConfiguration、@ComponentScan這三個註解比較重要

@Configuration(@SpringBootConfiguration點開檢視發現裡面還是應用了@Configuration):

這裡的@Configuration對我們來說不陌生,它就是JavaConfig形式的Spring Ioc容器的配置類使用的那個@Configuration,SpringBoot社群推薦使用基於JavaConfig的配置形式,所以,這裡的啟動類標註了@Configuration之後,本身其實也是一個IoC容器的配置類。

@Configuration
public class MockConfiguration{
    @Bean
    public MockService mockService(){
        return new MockServiceImpl(dependencyService());
    }
    
    @Bean
    public DependencyService dependencyService(){
        return new DependencyServiceImpl();
    }
}

@EnableAutoConfiguration

Spring框架有提供各種名字為@Enable開頭的Annotation定義,比如@EnableScheduling、@EnableCaching、@EnableMBeanExport等,@EnableAutoConfiguration的理念和做事方式其實一脈相承,簡單概括一下就是,藉助@Import的支援,收集和註冊特定場景相關的bean定義。

例如:

@EnableScheduling是通過@Import將Spring排程框架相關的bean定義都載入到IoC容器。

@EnableMBeanExport是通過@Import將JMX相關的bean定義載入到IoC容器。

而@EnableAutoConfiguration也是藉助@Import的幫助,將所有符合自動配置條件的bean定義載入到IoC容器,僅此而已!

@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(EnableAutoConfigurationImportSelector.class),該類的selectImports方法中呼叫的getCandidateConfigurations方法中,使用了SpringFactoriesLoader.loadFactoryNames方法,SpringFactoriesLoader屬於Spring框架私有的一種擴充套件方案,其主要功能就是從指定的配置檔案META-INF/spring.factories載入配置。即Spring會根據@EnableAutoConfiguration的完整類名org.springframework.boot.autoconfigure.EnableAutoConfiguration作為查詢的Key,獲取對應的一組@Configuration類,如下所示:

@EnableAutoConfiguration自動配置的本質:從classpath中搜尋所有的META-INF/spring.factories配置檔案,並將其中org.springframework.boot.autoconfigure.EnableutoConfiguration對應的配置項通過反射(Java Refletion)例項化為對應的標註了@Configuration的JavaConfig形式的IoC容器配置類,然後彙總為一個並載入到IoC容器。

 

@ComponentScan

@ComponentScan這個註解在Spring中很重要,它對應XML配置中的元素,@ComponentScan的功能其實就是自動掃描並載入符合條件的元件(比如@Component和@Repository等)或者bean定義,最終將這些bean定義載入到IoC容器中。

我們可以通過basePackages等屬性來細粒度的定製@ComponentScan自動掃描的範圍,如果不指定,則預設Spring框架實現會從宣告@ComponentScan所在類的package進行掃描。

注:所以SpringBoot的啟動類最好是放在root package下,因為預設不指定basePackages。