大家好,又见面了,我是你们的朋友全栈君。
创建项目
通过Spring Initialize创建SpringBoot项目
而接下来要说的是关于配置文件的事情。关乎配置文件可以参考官方文档。
对于配置文件来说到底在配置文件里面可以进行配置那些内容,自动配置的原理又是什么东西呢?
自动配置原理
在SpringBoot启动的时候加载主配置类,开启了自动配置的功能,通过@EnableAutoConfiguration注解开启自动配置的功能。@Import({EnableAutoConfigurationImportSelector.class})通过这个功能导入了SpringBoot自动配置的选择器。
AutoConfigurationImportSelector类
在这个类中有一个selectImports方法通过这个方法进行导入组件。在这个方法中最后的返回值是一个configurations
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
configurations = this.sort(configurations, autoConfigurationMetadata);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return (String[])configurations.toArray(new String[configurations.size()]);
} catch (IOException var6) {
throw new IllegalStateException(var6);
}
}
}
作为整个方法的返回值,通过一个getCandidateConfigurations方法进行返回进入到对应的方法中可以看到
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.");
return configurations;
}
SpringFactoriesLoader.loadFactoryNames 方法
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
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 propertyValue = properties.getProperty(factoryClassName);
String[] var8 = StringUtils.commaDelimitedListToStringArray(propertyValue);
int var9 = var8.length;
for(int var10 = 0; var10 < var9; ++var10) {
String factoryName = var8[var10];
result.add(factoryName.trim());
}
}
return result;
} catch (IOException var12) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var12);
}
}
这个方法扫描所有jar包的类路径下的内容,META-INF/spring.factories在之前,也看过这文件里面的内容,这里提供一个新的位置
在这个里我们可以看到这里有很多的自动配置的类。这些类有见过的也没有见过的,有之前用过的,也有之前没有用过的。这个方法通过将这些内容。然后包装成了properties。在这个方法中有一个factoryClassName参数,这个参数通过下面的这个方法获取到
protected Class<?> getSpringFactoriesLoaderFactoryClass() {
return EnableAutoConfiguration.class;
}
从properties中获取到EnableAutoConfiguration.class类对应的值,把它们添加到容器中。而这个值就是在上面的那个图中说道的那个配置文件的值。相当于将EnableAutoConfiguration类下的所有内容都加入到容器中。所以在容器中最终会有很多的类。这里就不在详细的介绍这些类了。用到的时候在进行说明。
通过仔细观察可以知道这里的类名都是xxxAutoConfiguration。这个就表示自动配置的功能。在这里可以通过一个简单的自动配置类进行配置。
实例
HttpEncodingAutoConfiguration自动配置类
首先进入这个类会看到在这个类上面有很多的注解。这里首先一个个的看一下这些注解都是什么意思。
@Configuration
@EnableConfigurationProperties(HttpEncodingProperties.class)
@ConditionalOnWebApplication
@ConditionalOnClass(CharacterEncodingFilter.class)
@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true)
@Configuration
表示这个是一个配置类,这个配置类也会在容器中添加组件
@EnableConfigurationProperties(HttpEncodingProperties.class)
启用@EnableConfigurationProperties配置功能,后面跟了一个类。这个类就表示这配置内容是什么
@ConfigurationProperties(prefix = "spring.http.encoding")
从配置文件中获取到指定的值和bean与对应的属性进行绑定。这个原理在之前的时候使用的时候也提到过。
public class HttpEncodingProperties {
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
从这里可以看出基于SpringBoot的所有的配置都可以是通过一个类似于这样的配置类进行操作。
@ConditionalOnWebApplication
在Spring中底层有一个@Conditional注解这个注解表示根据不同的条件如果满足指定的条件,整个配置类里面的配置就会生效。而这个注解就是判断是否满足Web应用。如果是web应用,当前的配置生效,如果不是则不生效。
@ConditionalOnClass(CharacterEncodingFilter.class)
判断当前项目有没有对应的括号中的类,而这个过滤器就是在SpringMVC中过滤乱码的一个拦截器。
@ConditionalOnProperty(prefix = “spring.http.encoding”, value = “enabled”, matchIfMissing = true)
判断配置文件中是否存在某个配置。如果不存在,matchIfMissing 则判断成立。
上面的这些就是整体判断所有的条件都成功之后就会真正的使用到这个配置类。这个配置类生效之后又有那些内容。可以注入到容器中。一旦这个类生效,在这个类中的组件也会对应生效。但是这些组件的内容是对应的属性是从properties中获取的,这些类的每一个属性又是和配置文件绑定的。
继续往下看就会发现有新的内容
@Bean
@ConditionalOnMissingBean(CharacterEncodingFilter.class)
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;
}
给容器中添加一个组件。也就是说通过@Bean的方式向容器中注入了一个Filter组件,而这个组件就是CharacterEncodingFilter类的对象,并且通过properties中获取对应的属性值。private final HttpEncodingProperties properties,它已经和SpringBoot的配置文件做了映射,也就说这个对象的值是获取了配置文件的值。
在这个类中还有一个比较值的关注的地方就是这个有参构造函数。在只有一个有参构造器的情况下。参数的值就会从容器中获取到,在之前的时候我们看到过一个@EnableConfigurationProperties(HttpEncodingProperties.class)注解,这个注解的就是将这个类HttpEncodingProperties进行了映射。
public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
this.properties = properties;
}
分析到这里,就可以看到HttpEncodingProperties在这个类中的很多的属性,在配置文件中都可以进行配置。
在我们进行配置的时候就会看到这么多的关于HTTPencoding。在以后使用的时候可以通过查看源码获取到对应属性的用法。
在使用配置的时候,可以知道这个属性的都是通过这属性对应的properties类。
总结
- SpringBoot启动会加载很多的自动配置类。所以我们需要的功能是不是有SpringBoot自己写好的自动配置类,
- 然后查看对应的配置类中有那些组件,只要需要的组件在SpringBoot组件中有,就不需要在配置了。
- 给容器中,自动添加组件的时候,会从Properties类中获取到某些属性,而这些属性就可以在配置文件中指定对应的值。
在SpringBoot中使用了很多的这样的模式,通过自动配置类向容器中添加组件,然后通过对应的Properties中的属性进行配置。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/149965.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...