自动配合原理
自动配置原理:
1、SpringBoot启动的时候,加载主配置类,开启了自动配置功能 @EnableAutoConfiguration
2、@EnableAutoConfiguration
作用:
利用@Import(AutoConfigurationImportSelector.class)
给容器中导入一些组件
可以查看插件AutoConfigurationImportSelector
类的关系;
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
3、可以看到AutoConfigurationImportSelector
类实现了很多接口,其中DeferredImportSelector
接口要在带有Aware
后缀加载之后执行。这里重点看DeferredImportSelector
接口的selectImports
方法。
/**
* Return the {@link Entry entries} of which class(es) should be imported
* for this group.
*/
Iterable<Entry> selectImports();
4、查看selectImports
的实现方法
@Override
public Iterable<Entry> selectImports() {
if (this.autoConfigurationEntries.isEmpty()) {
return Collections.emptyList();
}
Set<String> allExclusions = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
.collect(Collectors.toCollection(LinkedHashSet::new));
processedConfigurations.removeAll(allExclusions);
return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
.collect(Collectors.toList());
}
5、找到 返回值getAutoConfigurationMetadata
的方法
private AutoConfigurationMetadata getAutoConfigurationMetadata() {
if (this.autoConfigurationMetadata == null) {
this.autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
}
return this.autoConfigurationMetadata;
}
6、查看AutoConfigurationMetadataLoader
类
final class AutoConfigurationMetadataLoader {
protected static final String PATH = "META-INF/spring-autoconfigure-metadata.properties";
得到了类路径。
将类路径下 META-INF/spring.factories 里面配置的所有EnableAutoConfiguration的值加入到容器中
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到了容器中,用他们来做自动配置
3、每一个自动配置类进行自动配置功能
以**HttpEncodingAutoConfiguration
**为例,解释自动配置原理;
@Configuration(proxyBeanMethods = false) // 表示这是一个配置类,和编写的配置文件一样,还可以给容器添加组件
@EnableConfigurationProperties(ServerProperties.class) // 启动ConfigurationProperties功能,将配置文件对应的值和本类绑定起来了
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) //Spring底层@Conditional注解,根据不同的条件,如果满足指定的条件,整个配置类的配置就会生效(判断当前应用是否是web应用)
@ConditionalOnClass(CharacterEncodingFilter.class) // 判断当前项目,有没有这个类(CharacterEncodingFilter)
@ConditionalOnProperty(prefix = "server.servlet.encoding", value = "enabled", matchIfMissing = true)
// 判断配置文件是否存在"server.servlet.encoding"."enabled" 如果不存在,判断也会成立的
public class HttpEncodingAutoConfiguration {
// 这个已经和SpringBoot映射了
private final Encoding properties;
// 只有一个有参构造器的情况下,参数的值就会从容器中拿。
public HttpEncodingAutoConfiguration(ServerProperties properties) {
this.properties = properties.getServlet().getEncoding();
}
@Bean // 给容器中添加一个组件,这个组件的某些值,需要从properties中获取
@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;
}
根据当前不同的条件判断,决定这个配置类是否生效
一旦这个配置类生效,这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的properties类中获取的,这些类的每一个属性又是和配置文件绑定的。
4、所有在配置文件中,能配置的属性都是在xxxProperties类中封装着;配置文件能配置什么,就可以参照某个对应的功能类
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true) // 从配置文件中获取指定的值和Bean的属性进行绑定。
public class ServerProperties {
精髓:
- Spring Boot 启动会加载大量的自动配置类
- 我们需要的功能有没有SpringBoot写好的配置类;
- 我们再来看自动配置中到底配置了哪些组件;(只要我们用的组件有,我们就不需要再配置了)
- 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值
xxxAutonConfiguration:自动配置类;
给容器中添加组件
xxxProperties:封装配置文件中相关的属性;