SpringBoot簡化設定分析總結

2020-10-09 11:00:24

SpringBoot簡化設定分析總結

在SpringBoot啟動類中,該主類被@SpringBootApplication所修飾,跟蹤該註解類,除元註解外,該註解類被如下自定註解修飾。

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

讓我們簡單敘述下它們各自的功能:

  • @ComponentScan:掃描需要被IoC容器管理下需要管理的Bean,預設當前根目錄下的
  • @EnableAutoConfiguration:裝載所有第三方的Bean
  • @SpringBootConfiguration 作用等同於@Configuration

我們來看下@SpringBootConfiguration

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}

可以看到該註解類內包含與@Configuration,其作用與@Configuration並無太大區別,只是多了層屬性巢狀。

故: @SpringBootConfiguration + @ComponentScan

將根目錄下所有被**@Controller、@Service、@Repository、@Component**等所修飾的類交給IoC容器管理。

那麼重點來了,@EnableAutoConfiguration是如何裝載第三方Bean的呢?讓我們跟蹤下它的原始碼。

首先我們可以看到該類被如下註解修飾:

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})

我們先關注下AutoConfigurationImportSelector這個元件。

// 批次匯入第三方的一些Bean
@Import({AutoConfigurationImportSelector.class})

其中該元件的selectImports(AnnotationMetadata annotationMetadata)方法,掃描所有需要被管理的第三方Bean並交給IoC容器進行管理。

那麼SpringBoot又是如何取感知第三方的Bean檔案呢?

SpringBoot和第三方Bean之間存在一定的規定。即通過對於相應依賴的Jar包中可能存在一個spring.factories檔案,在該檔案中就記錄了需要被IoC容器管理的Bean檔案路徑,SpringBoot通過該檔案確定需要IoC管理的Bean檔案位置。對於spring-boot-autoconfiguration的spring.factories檔案中,記錄著大量xxxAutoConfiguration的類檔案位置,這些類都被@Configuration註解標識,即這些設定類會設定多個Bean從而解決spring.factories可能產生的臃腫問題。

Tomcat的載入時機

對於SpringBoot來說它特點不僅是簡化設定,還有內嵌容器等特點。那麼就有必要探討Tomcat容器的載入時機。在spring-boot-autoconfiguration的spring.factories檔案中存在ServletWebServerFactoryAutoConfiguration設定類的路徑,該類會在專案啟動時將預設的Tomcat容器已@Bean的方式載入入IoC容器內部。

SpringBoot是如何集中設定呢?

談論這個問題前我們不妨先按照之前yml或properties的檔案設定下

server:
  port: 8080

通過IDE,跟蹤到port所設定的成員變數所在類,發現該類被@ConfigurationProperties所修飾,該註解就是將yml或properties中設定按照對應字首注入到指定類的成員變數。該註解具體實現感興趣的小夥伴們可以去如下連結學習。@ConfigurationProperties實現原理與實戰

@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
   private Integer port;
*******
}

下面兩個程式碼和前述作用大致相同

environment.getProperty("xxx");

@Value("${xxx}")

已經知道了SpringBoot如何簡化設定,那麼我們也可以自己來實現一個starter交給SpringBoot來使用,只要在對應Jar包中新增spring.factories檔案,在其中新增如下程式碼

org.springframework.boot.autoconfigure.EnableAutoConfiguration=xxxAutoConfiguration

大家若有時間還請實現下自己的starter依賴,對加深這部分理解還是很有幫助的。

最後我們在說下最後@SpringBootApplication中@AutoConfigurationPackage這個註解類,發現其中匯入了Registrar元件。

@Import({Registrar.class})

讓我們重點關注registerBeanDefinitions這個方法,該方法最終會來到DefaultListableBeanFactory中registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法,將AutoConfigurationPackages.Registrar.class匯入到IoC容器中,然後將主設定類所在包下所有元件匯入到SpringIoC容器中

怎麼樣,在為我們簡化了設定的同時,SpringBoot居然幫我們做了如此多的事情,而我們只需要簡單地集中設定其中一部分的屬性。關於SpirngBoot我們就探討到這裡,這些內容是閱讀一些文章,觀看部分講解和原始碼的總結,若有錯誤還請接納與指教。最後感謝各位的閱讀。