好程式設計師Java培訓分享SpringBoot -自動配置原理

好程式設計師發表於2020-07-31

   好程式設計師Java 培訓分享 SpringBoot - 自動配置原理 概要 SpringBoot 啟動的時候載入主配置類,開啟了自動配置功能 @EnableAutoConfiguration

   利用EnableAutoConfigurationImportSelector 給容器中匯入一些元件可以檢視 selectImports() 方法的內容

   List configurations = getCandidateConfigurations(annotationMetadata, attributes); 獲取候選的配置

   SpringFactoriesLoader.loadFactoryNames() 掃描所有 jar 包類路徑下 META INF/spring.factories

   把掃描到的這些檔案的內容包裝成properties 物件,從 properties 中獲取到 EnableAutoConfiguration.class ( 類名 ) 對應的值,然後把他們新增在容器中

   @EnableAutoConfiguration

   作用

   @EnableAutoConfiguration 這個類很重要 , 主要的作用是自動載入應用程式所需要的所有預設配置 , 達到智慧的自動配置作用

 

主要是透過他來實現約定大於配置

 

原始碼

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

// 自動配置包

@AutoConfigurationPackage

// IOC 容器匯入元件

@Import(AutoConfigurationImportSelector.class)

public @interface EnableAutoConfiguration {

    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

 

    String[] excludeName() default {};

}

說明

@Import(AutoConfigurationImportSelector.class) 這個註解裡的 AutoConfigurationImportSelector 最為重要

 

利用AutoConfigurationImportSelector @EnableAutoConfiguration 可以幫助 SpringBoot 應用將所有符合條件的 @Configuration 配置都載入到當前 SpringBoot 建立並使用的 IoC 容器。

 

AutoConfigurationImportSelector

selectImports() 方法

首先執行selectImports() 方法 中呼叫 getAutoConfigurationEntry()

 

public String[] selectImports(AnnotationMetadata annotationMetadata) {

    ...

        AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,

                annotationMetadata);

        return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());

    }

getAutoConfigurationEntry

該方法主要作用獲取EnableAutoConfiguration 中的屬性 , 呼叫 getCandidateConfigurations() 方法

 

protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,

            AnnotationMetadata annotationMetadata) {

            ...

          List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);

         ..

    }

getCandidateConfigurations

獲取候選的配置資訊, 在候選資訊的中使用 SpringFactoriesLoader.loadFactoryNames()

 

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;

    }

SpringFactoriesLoader

這個類中有一個比較重要的工具類SpringFactoriesLoader 主要功能就是從指定的配置檔案 META-INF/spring-factories 載入配置, spring-factories 是一個典型的 java properties 檔案,只不過 Key Value 都是 Java 型別的完整類名,

 

主要的作用:

 

掃描所有jar 包類路徑下 META-INF/spring.factories

把掃描到的這些檔案的內容包裝成properties 物件 從 properties 中獲取到 EnableAutoConfiguration.class 類(類名)對應的值,

然後把他們新增在容器中 將類路徑下 META-INF/spring.factories 裡面配置的所有 EnableAutoConfiguration 的值加入到了容器中

/**

 * 使用內部工具 SpringFactoriesLoader ,查詢 classpath 上所有 jar 包中的 META-INF\spring.factories

 * 找出其中 key org.springframework.boot.autoconfigure.AutoConfigurationImportFilter 的屬性定義的過濾器類並例項化。

 * AutoConfigurationImportFilter 過濾器可以被註冊到 spring.factories 用於對自動配置類做一些限制,在這些自動配置類的位元組碼被讀取之前做快速排除處理。

 * spring boot autoconfigure 預設註冊了一個 AutoConfigurationImportFilter :

 **/

    public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {

        String factoryClassName = factoryClass.getName();

        return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());

    }

# Auto Configure

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\

org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\

org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\

org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\

org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\

org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\

org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\

org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\

org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\

org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\

org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\

org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\

org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\

org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\

MultipartAutoConfiguration( 檔案上傳 ) 為例

// 表示這是一個配置類

@Configuration

// 判斷當前專案有沒有這些類 有這些類則配置生效

@ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class })

// 判斷配置檔案中是否存在某個配置 spring.servlet.multipart.enabled

@ConditionalOnProperty(prefix = "spring.servlet.multipart", name = "enabled", matchIfMissing = true)

//   判斷當前應用是否是 web 應用,如果是,當前配置類生效

@ConditionalOnWebApplication(type = Type.SERVLET)

@EnableConfigurationProperties(MultipartProperties.class)

public class MultipartAutoConfiguration {

    // 配置檔案中對應的 JavaBean

    private final MultipartProperties multipartProperties;

 

    public MultipartAutoConfiguration(MultipartProperties multipartProperties) {

        this.multipartProperties = multipartProperties;

    }

}

根據當前不同的條件判斷,決定這個配置類是否生效?一但這個配置類生效;這個配置類就會給容器中新增各種元件;這些元件的屬性是從對應的properties 類中獲取的,這些類中每一個屬性又是和配置檔案繫結;

 

MultipartProperties

所有在配置檔案中能配置的屬性都是在xxxxProperties 類中封裝者‘;配置檔案能配置什麼就可以參照某個功能對應的這個屬性類

 

@ConfigurationProperties(prefix = "spring.servlet.multipart", ignoreUnknownFields = false)

public class MultipartProperties {

    // 是否開啟檔案上傳功能  預設開啟

    private boolean enabled = true;

    // 上傳的路徑

    private String location;

 

    public void setMaxFileSize(DataSize maxFileSize) {

        this.maxFileSize = maxFileSize;

    }

 

    public void setMaxRequestSize(DataSize maxRequestSize) {

        this.maxRequestSize = maxRequestSize;

    }

 

  public void setResolveLazily(boolean resolveLazily) {

        this.resolveLazily = resolveLazily;

    }

public void setFileSizeThreshold(DataSize fileSizeThreshold) {

        this.fileSizeThreshold = fileSizeThreshold;

    }

}

spring:

  servlet:

    multipart:

      enabled: true

      location: /upload/files

      # 支援檔案寫入磁碟

      file-size-threshold: 0

      # 上傳檔案總的最大值

      max-request-size: 50MB

      # 單個檔案上傳的大小

      max-file-size: 5MB

      # 上傳時是否支援懶載入

      resolve-lazily: false

小結

SpringBoot 啟動會載入大量的自動配置類

自動配置類新增元件的時候,會從properties 類中獲取某些屬性。我們可以在配置檔案中指定這些屬性的值

xxxxAutoConfigurartion :自動配置類給容器中新增元件

 

xxxxProperties :對應配置檔案中相關屬性 , 在配置物件可以是 setter 方法 也有可以是屬性

 

根據當前不同的條件判斷,決定這個配置類是否生效。

 

一但這個配置類生效,這個配置類就會給容器中新增各種元件,這些元件的屬性是從對應的properties 類中獲取的,這些類裡面的每一個屬性又是和配置檔案繫結的。

 

5. 所有在配置檔案中能配置的屬性都是在 xxxxProperties 類中封裝者,配置檔案能配置什麼就可以參照某個功能對應的這個屬性類

 

@ConfigurationProperties(prefix = "spring.http.encoding")  // 從配置檔案中獲取指定的值和 bean 的屬性進行繫結

public class HttpEncodingProperties {

 

   public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

精髓:

 

1 )、 SpringBoot 啟動會載入大量的自動配置類

 

2 )、先看我們需要的功能有沒有 SpringBoot 預設寫好的自動配置類

 

3 )、再來看這個自動配置類中到底配置了哪些元件(只要我們要用的元件有,我們就不需要再來配置了)

 

4 )、給容器中自動配置類新增元件的時候,會從 properties 類中獲取某些屬性。我們就可以在配置檔案中指定這些屬性的值

 

xxxxAutoConfigurartion :自動配置類;給容器中新增元件;

 

xxxxProperties: 封裝配置檔案中相關屬性;


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69913864/viewspace-2708270/,如需轉載,請註明出處,否則將追究法律責任。

相關文章