1. 程式人生 > >我是如何做到springboot自動配置原理解析

我是如何做到springboot自動配置原理解析

一前言

springboot 2.0.0版本分析,整體的自動配置流程如下:

具體配置參考官方文件:springboot-doc

二 @SpringBootApplication

核心註解@SpringBootConfiguration其實就是@Configuration註解,表示是個配置類;@EnableAutoConfiguration表示springboot的自動配置機制;@ComponentScan表示掃描允許註冊額外的配置類;

@SpringBootApplication = @Configuration + @EnableAutoConfiguration + @ComponentScan

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 {

    // 排除不會被應用的自動配置類,classes形式
    @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")
    Class<?>[] exclude() default {};

    // 排除不會被應用的自動配置類,字串陣列形式
    @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
    String[] excludeName() default {};

    // 掃描基本包
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};

    // 掃描基本類
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
    Class<?>[] scanBasePackageClasses() default {};

}

三 AutoConfigurationImportSelector

點選@EnableAutoConfiguration 註解進入,看見@Import({AutoConfigurationImportSelector.class})是匯入AutoConfigurationImportSelector類;

AutoConfigurationImportSelector 類是自動配置的核心類,其主要進行配置的功能是配置factory.propertiesspring內嵌整合引入的配置;

3.1 具體依賴圖如下:

3.2 成員

    // 表示不引入配置
    private static final String[] NO_IMPORTS = new String[0];
    // 配置日誌
    private static final Log logger = LogFactory.getLog(AutoConfigurationImportSelector.class);
    // 排除的自動配置
    private static final String PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE = "spring.autoconfigure.exclude";
    // 宣告 beanFactory
    private ConfigurableListableBeanFactory beanFactory;
    // 宣告 environment (全域性環境)
    private Environment environment;
    // 宣告 beanClassLoader (bean的類載入器,載入spring-autoconfigure-metadata.properties中整合類)
    private ClassLoader beanClassLoader;
    // 宣告 resourceLoader (資源載入器,載入spring的 factory.properties配置類)
    private ResourceLoader resourceLoader;

3.3 selectImports

selectImports 這個方法的主要功能就是匯入factory.propertiesspring-autoconfigure-metadata.properties中的配置類;

 public String[] selectImports(AnnotationMetadata annotationMetadata) {
        if (!this.isEnabled(annotationMetadata)) {
            return NO_IMPORTS;
        } else {
            try {
              // 1 載入元資料資訊,本質就是載入bean,這裡的bean是指我我們spring-autoconfigure-metadata.properties中整合類
                AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
                // 2 AnnotationAttributes本質是個map
                AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
                // 3  獲得 spring.factories 中的配置類
                List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
                // 4  配置類複製用於排序不需要的配置類
                configurations = this.removeDuplicates(configurations);
                //  優先順序排序
                configurations = this.sort(configurations, autoConfigurationMetadata);
                // 需移除配置類
                Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
                // 校驗移除
                this.checkExcludedClasses(configurations, exclusions);
                // 執行移除配置類
                configurations.removeAll(exclusions);
                configurations = this.filter(configurations, autoConfigurationMetadata);
                this.fireAutoConfigurationImportEvents(configurations, exclusions);
                return StringUtils.toStringArray(configurations);
            } catch (IOException var6) {
                throw new IllegalStateException(var6);
            }
        }
    }

1 分析
AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);

進入方法發現載入的元資料資訊的路徑是 META-INF/spring-autoconfigure-metadata.properties

public static AutoConfigurationMetadata loadMetadata(ClassLoader classLoader) {
        return loadMetadata(classLoader, "META-INF/spring-autoconfigure-metadata.properties");
    }

在自動配置包底下找到spring-autoconfigure-metadata.properties


點進屬性檔案發現都spring自動配置類名的配置資訊,部分如下:

#Thu Mar 01 04:46:13 UTC 2018
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration=
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration.AutoConfigureAfter=org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration.Configuration=
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration.ConditionalOnClass=com.datastax.driver.core.Cluster,org.springframework.data.cassandra.core.ReactiveCassandraTemplate,reactor.core.publisher.Flux
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration.ConditionalOnClass=org.apache.solr.client.solrj.SolrClient,org.springframework.data.solr.repository.SolrRepository
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration=
............................

我們隨意點開其中的一個配置類,比如第一個HttpMessageConvertersAutoConfiguration,其中的class註解如下,可以發現其自動配置類都是通過註解配置;

// 表示配置類相當於xml中的 bean標籤
@Configuration
// 判定是否存在HttpMessageConverter.class類,如果不存在則引入
@ConditionalOnClass({HttpMessageConverter.class})
// 在這三個配置類配置之後再進行配置
@AutoConfigureAfter({GsonAutoConfiguration.class, JacksonAutoConfiguration.class, JsonbAutoConfiguration.class})
// 匯入配置類相當於xml中的 import標籤
@Import({JacksonHttpMessageConvertersConfiguration.class, GsonHttpMessageConvertersConfiguration.class, JsonbHttpMessageConvertersConfiguration.class})
public class HttpMessageConvertersAutoConfiguration {

3 分析

this.getCandidateConfigurations(annotationMetadata, attributes);方法的主要功能是獲取候選配置;

進入getCandidateConfigurations方法發現裡面的主要方法是loadFactoryNames;

// 獲得factory配置資訊類名
 protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.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;
    }

進入 loadFactoryNames 方法 主要是2部分;第一個是loadSpringFactories(classLoader),第二個是getOrDefault

// 載入factory類名
 public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
        String factoryClassName = factoryClass.getName();
        //  返回類名的list
        return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
    }

第一部分:
loadSpringFactories本質就是使用spring的Resource資源呼叫獲得 spring.factories 中的配置類;

// 載入spring.factories中的配置類資訊
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
        MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
        if (result != null) {
            return result;
        } else {
            try {
                // 獲得 `spring.factories` 配置類的URL
                Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
                LinkedMultiValueMap result = new LinkedMultiValueMap();
                // 將 `spring.factories`  每個配置類的key 和 val 儲存進 map
                while(urls.hasMoreElements()) {
                    URL url = (URL)urls.nextElement();
                    UrlResource resource = new UrlResource(url);
                    Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                    Iterator var6 = properties.entrySet().iterator();

                    while(var6.hasNext()) {
                        Entry<?, ?> entry = (Entry)var6.next();
                        List<String> factoryClassNames = Arrays.asList(StringUtils.commaDelimitedListToStringArray((String)entry.getValue()));
                        result.addAll((String)entry.getKey(), factoryClassNames);
                    }
                }

                cache.put(classLoader, result);
                return result;
            } catch (IOException var9) {
                throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var9);
            }
        }
    }

classLoader.getResources("META-INF/spring.factories") ;中找到自動配置包中的配置如下圖:

spring.factories裝載配置類部分資訊如下,沒錯這些配置都是sping啟動需要的配置類資訊,監聽器,過濾器,自動配置的start配置類,以及啟動的失敗的錯誤分析還有模板引擎的支援,詳細大家翻下配置包即可;

# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
....................................

第二部分:
getOrDefault是個Map集合,map中有這個key時,就使用這個key值,如果沒有就使用預設值defaultValue,返回也就是類名的list;

相關推薦

是如何做到springboot自動配置原理解析

一前言 springboot 2.0.0版本分析,整體的自動配置流程如下: 具體配置參考官方文件:springboot-doc 二 @SpringBootApplication 核心註解@SpringBootConfiguration其實就是@Configuration註解,表示是個配置類;@Enable

SpringBoot自動配置原理

override activity eve rop 哪些 isf 代碼 文件 multi SpringBoot自動配置原理 備註:該SpringBoot自動配置原理不適合java剛入門學者以及不熟悉Spring4+Springmvc+maven的同學 1、當Sprin

SpringBoot-自動配置原理

factory ESS bean att cond active tor 條件判斷 common 可配置項參考: https://docs.spring.io/spring-boot/docs/2.0.1.BUILD-SNAPSHOT/reference/htmlsingl

(轉)入門SpringBoot-自動配置原理(三)

leg ebs jdbc 路徑 ket dao posit 把他 exc 1、自動配置原理: 1)、SpringBoot啟動的時候加載主配置類,開啟了自動配置功能 ==@EnableAutoConfiguration== 2)、@EnableAutoConfigurat

SpringBoot專欄:SpringBoot自動配置原理以及細節(第三講)

  自動配置原理 1)、SpringBoot啟動的時候載入主配置類,開啟了自動配置功能 @EnableAutoConfiguration 2)、@EnableAutoConfiguration 作用:        利用EnableA

SpringBoot-自動配置原始碼解析

接著上一篇部落格《 SpringBoot-快速搭建WEB工程》提出的需要分析的三個方面:我們來深入的探究SpringBoot是如何在沒有一個配置檔案的情況下為我們啟動好一個完整的WEB工程的,首先我們從@SpringBootApplication 開始這裡的分析

SpringBoot學習筆記(三) SpringBoot 自動配置原理

SpringBoot自動配置 SpringBoot自動配置的註解是@EnableAutoConfiguration 所以來看@EnableAutoConfiguration註解的原始碼: 1、首先@EnableAutoConfiguration是包含在@S

springboot 自動配置原理

8、自動配置原理 配置檔案到底能寫什麼?怎麼寫?自動配置原理; 配置檔案能配置的屬性參照   1、自動配置原理: 1)、SpringBoot啟動的時候載入主配置類,開啟了自動配置功能 @EnableAutoConfiguration 2)、@EnableAutoConfigu

Springboot第二章 springboot 自動配置原理

springboot 官方文件記錄了properties/yml   能寫的所有配置 1、自動配置原理: 1)Sprintboot 啟動的時候,載入住配置類,開啟自動配置功能, @EnableAutoConfiguration 利用 @Import(Auto

springboot自動配置原始碼解析

springboot版本:2.1.6.RELEASE      SpringBoot 自動配置主要通過 @EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties&nb

SpringBoot自動裝配原理解析

>首先對於一個SpringBoot工程來說,最明顯的標誌的就是 `@SpringBootApplication`它標記了這是一個SpringBoot工程,所以今天的 SpringBoot自動裝配原理也就是從它開始說起。 ## 自動裝配流程 首先我們來看下@SpringBootApplication 這個註解的

SpringBoot自動配置原理原始碼級別分析

# SpringBoot自動配置原理 ### 前言 後面還會講到SpringBoot自動配置原理,會主要講解@EnableAutoConfiguratuon註解幫助我們做了什麼事情,是如何自動把自動配置類掃描到容器中的,建議看完這篇後,兩篇配合使用,[傳送門](https://blog.csdn.net/

SpringBoot自動配置原理過程解析

分享 類的方法 通過 fff 註解 autoconf resource name bsp SpringBoot的最大好處就是實現了大部分的自動配置,使得開發者可以更多的關註於業務開發,避免繁瑣的業務開發,但是SpringBoot如此好用的 自動註解過程著實讓人忍不住的去了解

SpringBoot自動配置註解原理解析

1. SpringBoot啟動主程式類: 1 @SpringBootApplication 2 public class DemoApplication { 3 public static void main(String[] args) { 4 5 SpringApp

spring boot啟動原理(包含自動配置解析

轉自:https://www.cnblogs.com/xiaoxi/p/7999885.html 我們開發任何一個Spring Boot專案,都會用到如下的啟動類 1 @SpringBootApplication 2 public class Application { 3 publ

springboot 2.* 自動配置原理探究&demo實現

springboot-2.1.0 自動配置原理解析&demo實現 前言 最近準備升級線上服務的版本到springboot 2.1.0,所以抽空重新研究學習了下springboot的一些特性、原理。本文的核心就是學習理解下springboot的自動配置原理,版本是目前springboot的最新rel

SpringBoot——web開發之SpringMVC自動配置原理

一、SpringBoot為SpringMVC提供的自動配置 2、SpringBoot為SpringMVC提供的自動配置:參考類WebMvcAutoConfiguration ①Inclusion of ContentNegotiatingViewResolver an

JAVAEE——SpringBoot配置配置檔案、YAML語法、檔案值注入、載入位置與順序、自動配置原理

# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAu

SpringBoot】spring-boot-自動配置原理

思考:配置檔案到底能寫什麼?怎麼寫?自動配置原理; 1.自動配置原理 springboot自動配置主演通過@EnableConfiguration,@Conditional,@EnableConfigurationProperties或者@ConfiguraionProp

springboot原始碼解析:自己實現一個springboot自動配置

上兩篇將到了springboot自動配置和條件註解是如何實現,這篇在前兩篇的基礎上自己實現一個springboot的自動配置,用到條件註解。 需求:加入自己手寫的jar。直接就可以使用StringRedisTemplate。 1.新建一個maven專案,pom.xml如下: