@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(ServerProperties.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass(CharacterEncodingFilter.class) @ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration { private final Encoding properties; public HttpEncodingAutoConfiguration(ServerProperties properties) { this.properties = properties.getServlet().getEncoding(); } @Bean @ConditionalOnMissingBean public CharacterEncodingFilter characterEncodingFilter() { CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter(); filter.setEncoding(this.properties.getCharset().name()); filter.setForceRequestEncoding(this.properties.shouldForce(Encoding.Type.REQUEST)); filter.setForceResponseEncoding(this.properties.shouldForce(Encoding.Type.RESPONSE)); return filter; }
@Configuration(proxyBeanMethods = false)
标记了@Configuration,其属性默认值是proxyBeanMethods = true
,表示Spring底层会给配置创建cglib动态代理。 作用:就是防止每次调用本类的Bean方法而重新创建对象,Bean是默认单例的。
这里值为false,表示默认创建多例bean 对象。
@Configuration用法参见 《JavaConfig形式中的@Configuration详解、CGLIB》
@EnableConfigurationProperties(ServerProperties.class)
声明可以在application.yml或application.properties文件中允许使用的属性。这些属性由对应的属性类映射而成。
@xxxConditional
根据当前不同的条件判断,决定这个配置类是否生效?
@Conditional派生注解(Spring注解版原生的@Conditional作用)
作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效。
原因是自动配置类只有在某些特定的场景下才会生效。就像吃饭时,叉子一般在吃西餐时才有用,筷子在吃中餐时才有用,可以这样声明 :
@Conditional(Type=XiCan) public class ChaZi { } @Conditional(Type=ZhongCan) public class KuaiZi { }
@ConditionalOnWebApplication
: 判断当前应用是否是web应用,如果是,当前配置类生效。
@ConditionalOnClass
:判断当前项目有没有这个类CharacterEncodingFilter,有的话才生效;自身的作用是SpringMVC中进行乱码解决的过滤器。
为什么要先判断是否有CharacterEncodingFilter类?很简单,因为字符处理要用到CharacterEncodingFilter类,强依赖该类。
@ConditionalOnProperty
:判断配置文件中是否存在配置项spring.http.encoding.enabled=true
,如果存在则当前配置类生效;如果不存在,判断也是成立的,即使我们配置文件中不配置spring.http.encoding.enabled=true,也是默认生效的,原因是matchIfMissing=true
,表示,如果不存在该配置项,则赋予其默认值true。
如果不想设置默认值的话,一般用法如下
@ConditionalOnProperty(prefix = "filter",name = "loginFilter",havingValue = "true")
,即通过havingValue 来判断true or false,如果缺失,就算false
更多的选项:
@Conditional 扩展注解作用(判断是否满足当前指定条件) @ConditionalOnJava 系统的java版本是否符合要求 @ConditionalOnBean 容器中存在指定Bean; @ConditionalOnMissingBean 容器中不存在指定Bean; @ConditionalOnExpression 满足SpEL表达式指定 @ConditionalOnClass 系统中有指定的类 @ConditionalOnMissingClass 系统中没有指定的类 @ConditionalOnSingleCandidate 容器中只有一个指定的Bean,或者这个Bean是首选Bean @ConditionalOnProperty 系统中指定的属性是否有指定的值 @ConditionalOnResource 类路径下是否存在指定资源文件 @ConditionalOnWebApplication 当前是web环境 @ConditionalOnNotWebApplication 当前不是web环境 @ConditionalOnJndi JNDI存在指定项
HttpEncodingAutoConfiguration究竟干了什么?有什么用?
参见《spring、servlet 、web.xml 解决中文乱码》
以往在spring配置字符过滤器的方法,在web.xml只配置:
<!-- 配置utf-8编码过滤器 --> <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> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
其实,SpringBoot也是采用CharacterEncodingFilter这个过滤器实现的,只不过是自动配置,characterEncodingFilter()就是完成自动配置CharacterEncodingFilter过滤器的:
public class HttpEncodingAutoConfiguration { @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; }