原始碼學習系列之SpringBoot自動配置(篇二)
原始碼學習系列之SpringBoot自動配置(篇二)之HttpEncodingAutoConfiguration 原始碼分析
繼上一篇部落格原始碼學習系列之SpringBoot自動配置(篇一)之後,本部落格繼續跟一下SpringBoot的自動配置原始碼
ok,先複習一下上一篇的內容,從前面的學習,我們知道了SpringBoot的自動配置主要是由一個選擇器AutoConfigurationImportSelector,先通過選擇器將自動配置的類載入到Spring容器
注意點:
List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
- 由SpringFactoriesLoader載入器負責載入配置類名,已經裝載配置類到容器,SpringFactoriesLoader的loadSpringFactories方法讀取自動配置工程的META-INF/spring.factories配置檔案,載入配置類的全類名,包裝成Properties物件,然後再載入到容器裡
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; /* 將spring.factories的類都裝載到Spring容器*/ public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) { String factoryClassName = factoryClass.getName(); try { //將META-INF/spring.factories檔案裡配置的屬性都裝載到Enumeration資料結構裡 Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"); ArrayList result = new ArrayList(); //遍歷獲取屬性,然後再獲取對應的配置類全類名 while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url)); String factoryClassNames = properties.getProperty(factoryClassName); result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames))); } return result; } catch (IOException var8) { throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8); } }
ok,Springboot的自動配置類都在這個包裡,原始碼很多,所以本部落格只是簡單跟一下原始碼
自動配置可以說是SpringBoot框架的一個很重要的功能,其強大的功能就是通過很多配置類實現的,當然這麼多配置,可以參考SpringBoot官方的配置參考:
https://docs.spring.io/spring-boot/docs/2.1.10.RELEASE/reference/html/common-application-properties.html
SpringBoot的自動配置類很多,顯然不是每個配置類都生效的,比如你沒引對應的jar,那對應的配置類肯定是不起效的,ok,本部落格以HttpEncodingAutoConfiguration自動編碼配置類為例項,記錄一下SpringBoot的自動配置
先補充一些@Conditional註解的用法:詳情可以參考我上篇部落格SpringBoot系列之@Conditional註解用法簡介
@Conditional派生註解 | 作用(都是判斷是否符合指定的條件) |
---|---|
@ConditionalOnJava | 系統的java版本是否符合要求 |
@ConditionalOnBean | 有指定的Bean類 |
@ConditionalOnMissingBean | 沒有指定的bean類 |
@ConditionalOnExpression | 符合指定的SpEL表示式 |
@ConditionalOnClass | 有指定的類 |
@ConditionalOnMissingClass | 沒有指定的類 |
@ConditionalOnSingleCandidate | 容器只有一個指定的bean,或者這個bean是首選bean |
@ConditionalOnProperty | 指定的property屬性有指定的值 |
@ConditionalOnResource | 路徑下存在指定的資源 |
@ConditionalOnWebApplication | 系統環境是web環境 |
@ConditionalOnNotWebApplication | 系統環境不是web環境 |
@ConditionalOnjndi | JNDI存在指定的項 |
通過上篇部落格的學習,我們已經知道了SpringBoot有很多自動配置類,所以本部落格拿HttpEncodingAutoConfiguration類來看看
補充:
- @Configuration proxyBeanMethods屬性:預設是開啟的,開啟後允許其它配置類呼叫這個類的@bean方法,詳情參看Spring官方文件:Spring官方文件
package org.springframework.boot.autoconfigure.web.servlet;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.autoconfigure.http.HttpProperties;
import org.springframework.boot.autoconfigure.http.HttpProperties.Encoding;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.web.filter.CharacterEncodingFilter;
@Configuration(
proxyBeanMethods = false
)//指定是一個配置列,關了proxyBeanMethods,其它配置類就不能調相應的@bean類
@EnableConfigurationProperties({HttpProperties.class})//讓使用 @ConfigurationProperties註解的HttpProperties類生效,HttpProperties類通過ConfigurationProperties註解,將屬性配置一個一個載入進來
@ConditionalOnWebApplication(
type = Type.SERVLET
)//指定系統環境是Web環境配置才起效,並且指定型別是SERVLET
@ConditionalOnClass({CharacterEncodingFilter.class})//系統有CharacterEncodingFilter過濾器類,則配置類起效,CharacterEncodingFilter類:SpringMVC中進行亂碼解決的過濾器
@ConditionalOnProperty(
prefix = "spring.http.encoding",
value = {"enabled"},
matchIfMissing = true
)//判斷配置檔案是否有spring.http.encoding.enabled屬性,如果沒配置,也是預設為true的,因為配置了`matchIfMissing =true`
public class HttpEncodingAutoConfiguration {
//建立一個Encoding物件
private final Encoding properties;
// 建構函式裡通過properties.getEncoding();進行屬性對映,獲取預設的配置
public HttpEncodingAutoConfiguration(HttpProperties properties) {
this.properties = properties.getEncoding();
}
@Bean
@ConditionalOnMissingBean//如果系統沒有CharacterEncodingFilter類,就執行characterEncodingFilter方法
public CharacterEncodingFilter characterEncodingFilter() {
//重新建立一個編碼過濾器
OrderedCharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
//設定預設的配置
filter.setEncoding(this.properties.getCharset().name());
filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
return filter;
}
@Bean
public HttpEncodingAutoConfiguration.LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
return new HttpEncodingAutoConfiguration.LocaleCharsetMappingsCustomizer(this.properties);
}
private static class LocaleCharsetMappingsCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {
private final Encoding properties;
LocaleCharsetMappingsCustomizer(Encoding properties) {
this.properties = properties;
}
public void customize(ConfigurableServletWebServerFactory factory) {
if(this.properties.getMapping() != null) {
factory.setLocaleCharsetMappings(this.properties.getMapping());
}
}
public int getOrder() {
return 0;
}
}
}
通過對HttpEncodingAutoConfiguration原始碼的學習,可以看出,其實主要是用@Conditional及其派生註解,這些註解都是要在特定情況才會起效,起效了,才會將元件載入到Spring容器裡
ok,然後我們怎麼知道哪些配置是起效的?在SpringBoot專案裡,是可以通過配置,開啟列印的,可以在application.properties加上debug=true
屬性就可以
控制檯列印的Positive matches就表示有效的配置類
console列印的Negative matches表示不起效的配置類:
比如我的專案沒有加aop的,aop自動配置類就不起效
相關推薦
原始碼學習系列之SpringBoot自動配置(篇二)
原始碼學習系列之SpringBoot自動配置(篇二)之HttpEncodingAutoConfiguration 原始碼分析 繼上一篇部落格原始碼學習系列之SpringBoot自動配置(篇一)之後,本部落格繼續跟一下SpringBoot的自動配置原始碼 ok,先複習一下上一篇的內容,從前面的學習,我們知道了S
原始碼學習系列之SpringBoot自動配置(篇一)
原始碼學習系列之SpringBoot自動配置原始碼學習(篇一) ok,本部落格嘗試跟一下Springboot的自動配置原始碼,做一下筆記記錄,自動配置是Springboot的一個很關鍵的特性,也容易被忽略的屬性,因為這個屬性被包括在@SpringBootApplication註解裡,所以不去跟一下原始碼都不知
SpringBoot原始碼學習系列之SpringMVC自動配置
目錄 1、ContentNegotiatingViewResolver 2、靜態資源 3、自動註冊 Converter, GenericConverter, and Formatter beans. 4、支援
王者系列之Mybatis入門配置(maven版本)
這次我們一起來做一個入門級別的持久層框架Mybatis的配置,正所謂完事開頭難。 1 引入依賴 <dependency> <groupId>org.mybatis</groupId>
Java入門系列之hashCode和equals(十二)
前言 前面兩節內容我們詳細講解了Hashtable演算法和原始碼分析,針對雜湊函式始終逃脫不掉hashCode的計算,本節我們將詳細分析hashCode和equals,同時您將會看到本節內容是從《Effective Java》學習整理而來(吐槽一句,這本書中文版翻譯的真垃圾),對於《Effective Ja
springboot學習筆記之SpringMVC自動配置原理
Springboot中自動配置Springmvc的檔案 @Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, D
SpringBoot 2.X課程學習 | 第三篇:自動配置(Auto-configuration)
一、auto-configuration introduction 自動配置是spri
SpringBoot原始碼學習系列之嵌入式Servlet容器
目錄 1、部落格前言簡單介紹 2、定製servlet容器 3、變換servlet容器 4、servlet容器啟動原理 SpringBoot原始碼學習系列之嵌入式Servlet容器
SpringBoot原始碼學習系列之啟動原理簡介
本部落格通過debug方式簡單跟一下Springboot application啟動的原始碼,Springboot的啟動原始碼是比較複雜的,本部落格只是簡單梳理一下原始碼,淺析其原理 為了方便跟原始碼,先找個Application類,打個斷點,進行除錯,如圖所示: step into,run方法呼叫了Sp
Spark2.0機器學習系列之7: MLPC(多層神經網絡)
element nbsp hid 隨機梯度下降 support file dict 分類器 希望 Spark2.0 MLPC(多層神經網絡分類器)算法概述 MultilayerPerceptronClassifier(MLPC)這是一個基於前饋神經網絡的分類器,它是一種在
機器學習系列之K-近鄰演算法(監督學習-分類問題)
''' @description : 演算法優點: a簡單、易於理解、易於實現、無需估計引數、無需訓練 演算法缺點: a懶惰演算法,對測試樣本分類時計算量大,記憶體開銷大 b必須制定k值,k值得選擇
SpringBoot學習筆記(三) SpringBoot 自動配置原理
SpringBoot自動配置 SpringBoot自動配置的註解是@EnableAutoConfiguration 所以來看@EnableAutoConfiguration註解的原始碼: 1、首先@EnableAutoConfiguration是包含在@S
ClickHouse學習系列之三【配置檔案說明】
背景 最近花了些時間看了下ClickHouse文件,發現它在OLAP方面表現很優異,而且相對也比較輕量和簡單,所以準備入門瞭解下該資料庫系統。在介紹了安裝和使用者許可權管理之後,本文對其配置檔案做下相關的介紹說明。 說明 Cl
Netty原始碼學習系列之1-NioEventLoopGroup的初始化
前言 NioEventLoopGroup是netty對Reactor執行緒組這個抽象概念的具體實現,其內部維護了一個EventExecutor陣列,而NioEventLoop就是EventExecutor的實現(看名字也可發現,一個是NioEventLoopGroup,一個是Nio
Netty原始碼學習系列之2-ServerBootstrap的初始化
前言 根據前文我們知道,NioEventLoopGroup和NioEventLoop是netty對Reactor執行緒模型的實現,而本文要說的ServerBootstrap是對上面二者的整合與呼叫,是一個統籌者和協調者。具體netty使用的是Reactor單執行緒模型還是多執行緒模
Netty原始碼學習系列之4-ServerBootstrap的bind方法
前言 今天研究ServerBootstrap的bind方法,該方法可以說是netty的重中之重、核心中的核心。前兩節的NioEventLoopGroup和ServerBootstrap的初始化就是為bind做準備。照例貼上一下這個三朝元老的demo,開始本文內容。 1 publ
Netty原始碼學習系列之5-NioEventLoop的run方法
前言 NioEventLoop的run方法,是netty中最核心的方法,沒有之一。在該方法中,完成了對已註冊的channel上來自底層作業系統的socket事件的處理(在服務端時事件包括客戶端的連線事件和讀寫事件,在客戶端時是讀寫事件)、單執行緒任務佇列的處理(服務端的註冊事件、客
Spring5.0原始碼學習系列之淺談BeanFactory建立
Spring5.0原始碼學習系列之淺談BeanFactory建立過程 # 系列文章目錄 提示:[Spring原始碼學習專欄連結](https://blog.csdn.net/u014427391/category_10493299.html) # 部落格前言介紹 提示:在[上一章](https://s
Spring5.0原始碼學習系列之淺談迴圈依賴問題
## 前言介紹 附錄:[Spring原始碼學習專欄](https://blog.csdn.net/u014427391/category_10493299.html) 在[上一章](https://blog.csdn.net/u014427391/article/details/109625421)的學習中
Spring5.0原始碼學習系列之Spring AOP簡述
## 前言介紹 附錄:[Spring原始碼學習專欄](https://blog.csdn.net/u014427391/category_10493299.html) 在前面章節的學習中,我們對Spring框架的IOC實現原始碼有了一定的瞭解,接著本文繼續學習Springframework一個核心的技術