自动配置原理
SpringBoot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration
@EnableAutoConfiguration作用:
利用AutoConfigurationImportSelector给容器导入了一些配置
1
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
通过getCandidateConfigurations(…)方法中调用的SpringFactoriesLoader.loadFactoryNames(…)扫描类路径下”META-INF/spring.factories”的所有资源。
1
SpringFactoriesLoader.FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
将扫描到的文件内容包装成properties对象。
再通过properties对象中获取EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中。
最终会将类路径下的 META-INF/spring.factories中配置的所有EnableAutoConfiguration的值加入到容器中。
每一个xxxAutoConfiguration类都是容器中的组件,都加入到容器中,来进行自动配置。
以HttpEncodingAutoConfiguration为例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46// 注解的方式表示这是一个配置类,跟以前编写的配置文件一样。
/* 启动指定类的 ConfigurationProperties功能,此处为 HttpProperties.class
* 将配置文件中对应的值和 HttpProperties绑定起来,详细如下 ^4.
*/
(HttpProperties.class)
/* Spring底层的 @Conditional注解(Spring注解版),根据不同的条件,
* 如果满足注解所要求的条件,则整个配置类生效。
* 此处是判断应用时候是web应用,如果是,当前配置类生效,并把HttpProperties加入到容器中
*/
(type = ConditionalOnWebApplication.Type.SERVLET)
/* 判断当前项目(系统)中有没有CharacterEncodingFilter.class这个类。
* 作用是用于解决SpringMVC中解决乱码的过滤器。
*/
(CharacterEncodingFilter.class)
/* 判断配置文件中是否存在某个配置 spring.http.encoding.enable;
* 如果不存在判断也是成立的。
* 即使在我们自己的文件中不配置 spring.http.encoding.enable = true,
* 在这里也默认配置生效了,原因->matchIfMissing = true
*/
"spring.http.encoding", value = "enabled", (prefix =
matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
// 它已经和springBoot的配置文件映射了
private final HttpProperties.Encoding properties;
// 只有一个有构造器的情况下,参数的值就会从容器中拿 ->@EnableConfigurationProperties
public HttpEncodingAutoConfiguration(HttpProperties properties) {
this.properties = properties.getEncoding();
}
// 给容器添加一个组件,这个组件的某些值需要从properties中获取
// 判断容器中没有这个组件,才向容器中添加。
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;
}
...
} 最终根据当前配置类注解的条件,来决定配置类是否生效。
一旦这配置类生效;这个配置类就会给容器添加各种组件,
这些组件的属性是从对应的properties中获取的,这些类的每一个属性都是和配置文件绑定的;
所有配置文件中能配置的属性都是在xxxProperties类中封装着,配置文件能配置什么就可以参照某个功能对应的这个属性类。
1
2
3
4
5
6
7
8// 从配置文件中获取指定的值和bean的属性进行绑定
"spring.http") (prefix =
public class Httpimport org.springframework.web.bind.annotation.RestController;
{
public static class Encoding {
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
}
}
作用
- 在了解了springboot2自动配置过程后,添加其他框架进行配置和使用时,可以通过查找相关框架的xxxxAutoConfiguration和xxxxProperties类来了解与springboot2的配合使用。
@Conditional注解扩展
@Conditional扩展注解 | 作用(判断是否满足当前指定条件) |
---|---|
@ConditionalOnJava | 系统中的java版本是否符合要求 |
@ConditionalOnBean | 容器中存在指定的bean |
@ConditionalOnMIssingBean | 容器中不存在指定的bean |
@ConditionalOnExpression | 满足SpEl表达式 |
@ConditionalOnClass | 系统中有指定的类 |
@ConditionalOnMIssingClass | 系统中没有指定的类 |
@ConditionalOnSingleCandidate | 容器中只有一个指定的bean,或者这个bean是首选 |
@ConditionalOnProperty | 系统中指定的属性是否有值 |
@ConditionalOnResource | 类路径下是否存在指定资源文件 |
@ConditionalOnWebApplication | 当前环境是web环境 |
@ConditionalOnNotWebApplication | 当前环境不是web环境 |
@ConditionalOnJndi | JNDI存在指定项 |