源码学习系列之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自动配置类就不起效