跳到主要內容

源碼學習系列之SpringBoot自動配置(篇二)

源碼學習系列之SpringBoot自動配置(篇二)之HttpEncodingAutoConfiguration 源碼分析


繼上一篇博客之後,本博客繼續跟一下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註解的用法:詳情可以參考我上篇博客



























































@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官方文檔:


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自動配置類就不起效

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能



※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享



※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選



※評比南投搬家公司費用收費行情懶人包大公開



Orignal From: 源碼學習系列之SpringBoot自動配置(篇二)

留言

這個網誌中的熱門文章

有了四步解題法模板,再也不害怕動態規劃!(看不懂算我輸)

導言 動態規劃問題一直是算法面試當中的重點和難點,並且動態規劃這種通過空間換取時間的算法思想在實際的工作中也會被頻繁用到,這篇文章的目的主要是解釋清楚 什麼是動態規劃 ,還有就是面對一道動態規劃問題,一般的 思考步驟 以及其中的注意事項等等,最後通過幾道題目將理論和實踐結合。 什麼是動態規劃 如果你還沒有聽說過動態規劃,或者僅僅只有耳聞,或許你可以看看 Quora 上面的這個 回答 。 How to explain dynamic 用一句話解釋動態規劃就是 " 記住你之前做過的事 ",如果更準確些,其實是 " 記住你之前得到的答案 "。 我舉個大家工作中經常遇到的例子。 在軟件開發中,大家經常會遇到一些系統配置的問題,配置不對,系統就會報錯,這個時候一般都會去 Google 或者是查閱相關的文檔,花了一定的時間將配置修改好。 過了一段時間,去到另一個系統,遇到類似的問題,這個時候已經記不清之前修改過的配置文件長什麼樣,這個時候有兩種方案,一種方案還是去 Google 或者查閱文檔,另一種方案是借鑒之前修改過的配置,第一種做法其實是萬金油,因為你遇到的任何問題其實都可以去 Google,去查閱相關文件找答案,但是這會花費一定的時間,相比之下,第二種方案肯定會更加地節約時間,但是這個方案是有條件的,條件如下: 之前的問題和當前的問題有着關聯性,換句話說,之前問題得到的答案可以幫助解決當前問題 需要記錄之前問題的答案 當然在這個例子中,可以看到的是,上面這兩個條件均滿足,大可去到之前配置過的文件中,將配置拷貝過來,然後做些細微的調整即可解決當前問題,節約了大量的時間。 不知道你是否從這些描述中發現,對於一個動態規劃問題,我們只需要從兩個方面考慮,那就是 找出問題之間的聯繫 ,以及 記錄答案 ,這裏的難點其實是找出問題之間的聯繫,記錄答案只是順帶的事情,利用一些簡單的數據結構就可以做到。 概念 上面的解釋如果大家可以理解的話,接    動態規劃 算法是通過拆分問題,定義問題狀態和狀態之間的關係,使得問題能夠以遞推(或者說分治)的方式去解決。它的幾個重要概念如下所述。    階段: 對於一個完整的問題過程,適當的切分為若干個相互聯繫的子問題,每次在求解一個子問題...

程序員需要了解的硬核知識之操作系統入門

對於程序員來說,最莫大的榮耀莫過於自己的軟件被大多數人使用了吧。 歷史文章請戳 本篇文章作為操作系統的入門文章,可能入門都算不上吧,畢竟操作系統太龐大和複雜了。本篇文章主要帶你了解一下我們常用的操作系統環境。 操作系統環境 程序中包含着 運行環境 這一內容,可以說 運行環境 = 操作系統 + 硬件 ,操作系統又可以被稱為軟件,它是由一系列的指令組成的。我們不介紹操作系統,我們主要來介紹一下硬件的識別。 我們肯定都玩兒過遊戲,你玩兒遊戲前需要干什麼?是不是需要先看一下自己的筆記本或者電腦是不是能肝的起遊戲?下面是一個遊戲的配置(懷念一下 wow) 圖中的主要配置如下 操作系統版本:說的就是應用程序運行在何種系統環境,現在市面上主要有三種操作系統環境,Windows 、Linux 和 Unix ,一般我們玩兒的大型遊戲幾乎都是在 Windows 上運行,可以說 Windows 是遊戲的天堂。Windows 操作系統也會有區分,分為32位操作系統和64位操作系統,互不兼容。 處理器:處理器指的就是 CPU,你的電腦的計算能力,通俗來講就是每秒鐘能處理的指令數,如果你的電腦覺得卡帶不起來的話,很可能就是 CPU 的計算能力不足導致的。想要加深理解,請閱讀博主的另一篇文章: 顯卡:顯卡承擔圖形的輸出任務,因此又被稱為圖形處理器(Graphic Processing Unit,GPU),顯卡也非常重要,比如我之前玩兒的 劍靈 開五檔(其實就是圖像變得更清晰)會卡,其實就是顯卡显示不出來的原因。 內存:內存即主存,就是你的應用程序在運行時能夠動態分析指令的這部分存儲空間,它的大小也能決定你電腦的運行速度,想要加深理解,請閱讀博主的另一篇文章 存儲空間:存儲空間指的就是應用程序安裝所佔用的磁盤空間,由圖中可知,此遊戲的最低存儲空間必須要大於 5GB,其實我們都會遺留很大一部分用來安裝遊戲。 從程序的運行環境這一角度來考量的話,CPU 的種類是特別重要的參數,為了使程序能夠正常運行,必須滿足 CPU 所需的最低配置。 CPU 只能解釋其自身固有的語言。不同的 CPU 能解釋的機器語言的種類也是不同的。機器語言的程序稱為 本地代碼(native code) ,程序員用 C 等高級語言編寫的程...

步伐密集 易事特再建江蘇充電樁專案

易事特今日發佈公告稱,與江蘇高淳經濟開發區開發總公司就新能源汽車充電樁設備研發製造、IDC整體機房研發製造、智慧微電網等項目投資達成一致意見並簽署協議書。易事特承諾新辦企業固定資產投資總額為6億元人民幣(約新臺幣30億),畝均稅收不低於20萬元(約新臺幣101萬),首期建築面積不低於30000平方米。高淳經濟開發區將供地約120畝,使用年限為50年。   易事特佈局充電樁可謂步伐密集。今年8月13日,易事特與馬鞍山經濟技術開發區管理委員會簽訂了《投資框架協議書》,擬在對方區域內投資建設資料中心、分散式發電設備與系統集成和新能源汽車充電站(樁)項目。 本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理 【其他文章推薦】 ※ USB CONNECTOR 掌控什麼技術要點? 帶您認識其相關發展及效能 ※ 台北網頁設計 公司這麼多該如何選擇? ※智慧手機時代的來臨,RWD 網頁設計 為架站首選 ※評比 南投搬家公司費用 收費行情懶人包大公開 ※幫你省時又省力, 新北清潔 一流服務好口碑 ※回頭車 貨運 收費標準 Orignal From: 步伐密集 易事特再建江蘇充電樁專案