SpringBoot 配置原理
自动配置原理
1、SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration
2、 @EnableAutoConfiguration的作用
1)、利用AutoConfigurationImportSelector类给容器导入一些组件
2)、AutoConfigurationImportSelector这个类里面调用了selectImports()方法的的getAutoConfigurationEntry()方法的核心
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); 获取候选配置
3)、点进这个方法中,它调用了loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());方法。
这个方法的作用就是扫描所有的jar包类路径下的META-INF/spring.factories 把扫描到的这些文件内容包装成properties对象
从properties中获取到EnableAutoConfiguration.class类(类名)对应的值,然后把它们添加在容器中
一句话讲,就是讲类路径下的 META-INF/spring.factories里面配置的所有EnableAutoConfiguration的值加入到容器中
每一个这样的xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用它们来做自动配置
4)、以 HttpEncodingAutoConfiguration为例解释自动配置原理
@Configuration(proxyBeanMethods = false) // 表示这是一个配置类,和以前编写的配置文件一样,也可以给容器中添加组件
@EnableConfigurationProperties(HttpProperties.class) // 启动指定的类ConfigurationProperties功能;
//将配置文件中对应的值和HttpEncodingProperties绑定起来
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) // 判断当前应用是否是web应用,如果是,当前配置类生效
//底层是Spring的@Conditional注解,根据不同的条件,满足条件的配置类才会生效
@ConditionalOnClass(CharacterEncodingFilter.class)// 判断当前项目有没有这个类 CharacterEncodingFilter:SpringMVC中进行乱码解决过滤器
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)// 判断我们配置文件中是否存在某个配置
// spring.http.encoding.enable; matchIfMissing=true表示如果不存在,判断也是成立的
// 即使我们文件中不配置spring.http.encoding.enable=true,也是默认生效的!
public class HttpEncodingAutoConfiguration {
// 已经和SpringBoot的配置文件映射了
private final HttpProperties.Encoding properties;
public HttpEncodingAutoConfiguration(HttpProperties properties) {
this.properties = properties.getEncoding();
}
@Bean // 给容器中添加组件。这个组件的某些值需要从properties中获取
@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;
}
.....
}