源碼學習系列之SpringBoot自動配置(篇二)之HttpEncodingAutoConfiguration 源碼分析html
繼上一篇博客源碼學習系列之SpringBoot自動配置(篇一)以後,本博客繼續跟一下SpringBoot的自動配置源碼java
ok,先複習一下上一篇的內容,從前面的學習,咱們知道了SpringBoot的自動配置主要是由一個選擇器AutoConfigurationImportSelector,先經過選擇器將自動配置的類加載到Spring容器web
注意點:spring
List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
獲取的候選配置的類名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的自動配置app
先補充一些@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類來看看函數
補充:spring-boot
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自動配置類就不起效