我是如何做到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.properties
和 spring內嵌整合
引入的配置;
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.properties
和 spring-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如下: