2.5 实例解析
在了解整个Spring Boot的运作原理之后,我们以Spring Boot内置的http编码功能为例,分析一下整个自动配置的过程。
在常规的Web项目中该配置位于web.xml,通过<filter>来进行配置。
<filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter>
而在Spring Boot中通过内置的HttpEncodingAutoConfiguration来完成这一功能。下面我们具体分析一下该功能都涉及哪些配置和实现。
根据前面讲的操作流程,我们先来看一下META-INF/spring.factories中对该自动配置的注册。
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ ... org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\ ...
当完成注册之后,在加载的过程中会使用元数据的配置进行过滤,对应的配置内容在META-INF/spring-autoconfigure-metadata.properties文件中。
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration.ConditionalOnClass=org.springframework.web.filter.CharacterEncodingFilter
在过滤的过程中要判断自动配置类HttpEncodingAutoConfiguration是否被@ConditionalOnClass注解,源代码如下。
@Configuration @EnableConfigurationProperties(HttpProperties.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass(CharacterEncodingFilter.class) @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration { private final HttpProperties.Encoding properties; public HttpEncodingAutoConfiguration(HttpProperties properties) { this.properties = properties.getEncoding(); } @Bean @ConditionalOnMissingBean public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE)); return filter; } ... }
很明显,它被@ConditionalOnClass注解,并且指定实例化的条件为类路径下必须有CharacterEncodingFilter存在。再看一下该类的其他注解。
·@Configuration:指定该类作为配置项来进行实例化操作。
·@EnableConfigurationProperties:参数为HttpProperties.class,开启属性注入,会将参数中的HttpProperties注入该类。
·@ConditionalOnWebApplication:参数为Type.SERVLET,说明该类只有在基于servlet的Web应用中才会被实例化。
·@ConditionalOnClass:参数为CharacterEncodingFilter.class,只有该参数存在,才会被实例化。
·@ConditionalOnProperty:指定配置文件内spring.http.encoding对应的值,如果为enabled才会进行实例化,没有配置则默认为true。
·@ConditionalOnMissingBean:注释于方法上,与@Bean配合,当容器中没有该Bean的实例化对象时才会进行实例化。
其中HttpProperties类的属性值对应着application.yml或application.properties中的配置,通过注解@ConfigurationProperties(prefix="spring.http")实现的属性注入。关于属性注入,后面章节会详细讲解,这里我们先看一下源代码和对应的配置文件参数。
@ConfigurationProperties(prefix = "spring.http") public class HttpProperties { ... public static class Encoding { public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; private Charset charset = DEFAULT_CHARSET; private Boolean force; private Boolean forceRequest; private Boolean forceResponse; private Map<Locale, Charset> mapping; ... } }
而在application.properties中,我们会进行如下对应配置:
spring.http.encoding.force=true spring.http.encoding.charset=UTF-8 spring.http.encoding.force-request=true ...