6、自动配置
a)、自动包加载规则
分析SpringBoot底层
首先来到主程序中找到SpringBoot注解@SpringBootApplication,进入源码,可以明显地发现这个注解是由
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
? ?excludeFilters = {@Filter(
? ?type = FilterType.CUSTOM,
? ?classes = {TypeExcludeFilter.class}
), @Filter(
? ?type = FilterType.CUSTOM,
? ?classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {}
这三个合成的,见过的就是一个 @CompentScan组件扫描。
进入@SpringBootConfiguration,可以发现
@Configuration
@Indexed
public @interface SpringBootConfiguration {
他是一个配置类。这样也能说明主程序类是一个配置类,暂时知道他是配置类就够了
进入@EnableAutoConfiguration注解源码里,这个注解完成了很多工作
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
进入后发现,第一个注解翻译过来是自动配置包,进入他的源码
@Import({Registrar.class})
public @interface AutoConfigurationPackage {
发现他引入了一个注册类组件
进入这个类的源代码中发现,这是一个静态加载类。
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
? ?AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
}
在里面由new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0])这一句把注册主程序类的包名拿到放进数组里最后返回。这样就拿到了该在程序启动时加载的包和进行组件扫描和其他工作
b)、初始加载自动配置
在刚才@EnableAutoConfiguration注解源码里,第一个注解完成了自动包加载
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
在第二个 引入的类组件中,这个方法里面
public String[] selectImports(AnnotationMetadata annotationMetadata) {
? ?if (!this.isEnabled(annotationMetadata)) {
? ? ? ?return NO_IMPORTS;
? } else {
? ? ? ?AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
? ? ? ?return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
? }
}
使用这个方法查询META文件夹中什么东西,主要发挥作用的是getAutoConfigurationEntry,进入它的源码
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
? ?if (!this.isEnabled(annotationMetadata)) {
? ? ? ?return EMPTY_ENTRY;
? } else {
? ? ? ?AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
? ? ? ?List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
? ? ? ?configurations = this.removeDuplicates(configurations);
? ? ? ?Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
? ? ? ?this.checkExcludedClasses(configurations, exclusions);
? ? ? ?configurations.removeAll(exclusions);
? ? ? ?configurations = this.getConfigurationClassFilter().filter(configurations);
? ? ? ?this.fireAutoConfigurationImportEvents(configurations, exclusions);
? ? ? ?return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
? }
}
发现方法内多次对configurations进行了操作,再继续往下看,发现这个对象是getCandidateConfigurations这个方法拿到的,点进去
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;
}
在里面有 META-INF/spring.factories.,这个就是configurations的来源,这个文件在spring-boot-autoconfigure-2.6.1.jar里面,它里面记载了程序实现过程中需要加载的组件【配置类】,但实际上是不会有这么多组件,
在spring.factories中
里面写死了SpringBoot加载过程中需要的配置类,127个,实际上不会加载这么多组件,可以通过按需配置让SpringBoot 加载配置类,在很多配置类里面有这个 注解@ConditionalOnClass即在有什么类的前提下才会加载特定组件
# 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,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration,\
org.springframework.boot.autoconfigure.netty.NettyAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveMultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebSessionIdResolverAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration
c)、自动配置流程
了解SpringBoot具体场景启动时的自动配置过程,以web为例
首先找到spring-boot-autoconfigure-2.6.1.jar
\org\springframework\boot\autoconfigure\web\servlet\DispatcherServletAutoConfiguration.class
来到DiapatcherServlerAutoConfiguration
先看到
//声明自己是一个配置类
@Configuration(
? ?proxyBeanMethods = false
)
//查看项目场景是不是原生servlet,当前项目是用的原生的servlet,所以符合
@ConditionalOnWebApplication(
? ?type = Type.SERVLET
)
//当前项目中有没有DiapacherServlet这个类,只要引入了SpringBoot就有,所以符合
@ConditionalOnClass({DispatcherServlet.class})
//在ServletWebServerFactoryAutoConfiguration配置完成后再进行配置
@AutoConfigureAfter({ServletWebServerFactoryAutoConfiguration.class})
public class DispatcherServletAutoConfiguration {}
上面发现条件都符合就可以进入类里面观察方法具体做了哪些功能
在类里面发现还有一个类
//说它是一个配置类
@Configuration(
? ?proxyBeanMethods = false
)
//当前项目有没有DispatcherServletRegistrationCondition这个类,是有的,符合
@Conditional({DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition.class})
//当前项目有没有ServletRegistration,这个类只要引入了tomcat配置,就有
@ConditionalOnClass({ServletRegistration.class})
//将WebMvcProperties注册为组件开启配置绑定功能
@EnableConfigurationProperties({WebMvcProperties.class})
//引入DispatcherServletConfiguration类
@Import({DispatcherServletAutoConfiguration.DispatcherServletConfiguration.class})
protected static class DispatcherServletRegistrationConfiguration {}
在上面看到@EnableConfigurationProperties将WebMvcProperties开启配置绑定,在WebMvcProperties中
//将application.propertis文件中前缀为spring.mvc的配置跟这个类里面的属性进行绑定,在后面需要绑定可以根据这里面的属性名进行设置值
@ConfigurationProperties(
? ?prefix = "spring.mvc"
)
public class WebMvcProperties {}
上面DispatcherServletRegistrationConfiguration类前面的条件都满足,继续看那个配置类
在DispatcherServletRegistrationConfiguration里面,注册一个组件名dispatcherServletRegistration为这个的组件
判断项目里有没有名字叫dispatcherServlet或者是类型是DispatcherServlet类型的组件,很明显有
protected static class DispatcherServletRegistrationConfiguration {
? ?protected DispatcherServletRegistrationConfiguration() {
? }
?
? ?@Bean(
? ? ? ?name = {"dispatcherServletRegistration"}
? )
? ?@ConditionalOnBean(
? ? ? ?value = {DispatcherServlet.class},
? ? ? ?name = {"dispatcherServlet"}
? )
? ?//在这个方法里就是SpringBoot自己创建了一个DispatcherServletRegistrationBean对象,并对各种属性设置好值,最后返回DispatcherServletRegistrationBean这个对象。
? ?所以说这个其实就是底层做好了DispatcherServlet配置
? ?public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet, WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
? ? ? ?DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet, webMvcProperties.getServlet().getPath());
? ? ? ?registration.setName("dispatcherServlet");
? ? ? ?registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
? ? ? ?multipartConfig.ifAvailable(registration::setMultipartConfig);
? ? ? ?return registration;
? }
}
在下面还有一个配置类
//声明自己是一个配置类
@Configuration(
? ?proxyBeanMethods = false
)
//有没有DefaultDispatcherServletCondition这个类,有,就在这个自动配置类【DispatcherServletAutoConfiguration】里面
@Conditional({DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition.class})
//有没有ServletRegistration这个组件,引入了tomcat依赖就有
@ConditionalOnClass({ServletRegistration.class})
//声明类WebMvcProperties为组件并且开启配置绑定
@EnableConfigurationProperties({WebMvcProperties.class})
//都通过,现在可以看底下的源码
protected static class DispatcherServletConfiguration {
? ?protected DispatcherServletConfiguration() {
? }
//注册一个名叫dispatcherServlet的组件
? ?@Bean(
? ? ? ?name = {"dispatcherServlet"}
? )
//在这个方法里手动new了一个DispatcherServlet对象并设置好了各种属性值,把本来需要配置文件做的事情在底层中已经设置好了,省去了自己设置的功夫,最后把dispatcherServlet对象返回
? ?public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
? ? ? ?DispatcherServlet dispatcherServlet = new DispatcherServlet();
? ? ? ?dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
? ? ? ?dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
? ? ? ?dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
? ? ? ?dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
? ? ? ?dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
? ? ? ?return dispatcherServlet;
? }
?
? ?@Bean
? ?//有没有MultipartResolver这个类型的组件
? ?@ConditionalOnBean({MultipartResolver.class})
? ?//当前项目中不存在一个名叫multipartResolver的MultipartResolver类型的组件
? ?这一步就是针对在自己设置文件上传MultipartResolver组件时命名不规范,当SpringBoot拿到这个组件时,名字不规范,他就在这里用下面的方法处理,把你不规范的用这个规范的替换掉,你那个不规范的实际上还在IOC容器中,只是在使用时不会被用到。
? ?@ConditionalOnMissingBean(
? ? ? ?name = {"multipartResolver"}
? )
? ? ? ?在MVC时,文件上传解析器的id必须叫multipartResolver
//这个方法就是当你调用这个方法后,他被标注了@Bean注解,他有参数就会自动去IOC容器中找MultipartResolver类型的组件,这个组件就是你注册的那个不规范的id,然后在方法里把你注册的这个文件上传解析器以方法名multipartResolver加到IOC容器中。这样MultipartResolver的名字就又叫multipartResolver
? ?public MultipartResolver multipartResolver(MultipartResolver resolver) {
? ? ? ?return resolver;
? }
}
第二个初始化有关的自动配置类HttpEncodingAutoConfiguration
//声明自己是一个配置类
@Configuration(
? ?proxyBeanMethods = false
)
//注册组件并开启配置绑定
@EnableConfigurationProperties({ServerProperties.class})
//判断是不是原生Servlet的项目,是的
@ConditionalOnWebApplication(
? ?type = Type.SERVLET
)
//判断当前有没有这个CharacterEncodingFilter,只要有SpringMvc的依赖,肯定就有
@ConditionalOnClass({CharacterEncodingFilter.class})
//有没有配置项前缀为server.servlet.encoding,值是enabled的,最后一个配置说明默认是有的
@ConditionalOnProperty(
? ?prefix = "server.servlet.encoding",
? ?value = {"enabled"},
? ?matchIfMissing = true
)
//可以去看内部实现了
public class HttpEncodingAutoConfiguration {}
类里面
public class HttpEncodingAutoConfiguration {
? ?//定义的一个Encoding类型的属性,这个类型在CharacterEncodingFilter里面有,之前Mvc用过
? ?private final Encoding properties;
?
? ?//规定属性值从哪里获取到
? ?public HttpEncodingAutoConfiguration(ServerProperties properties) {
? ? ? ?this.properties = properties.getServlet().getEncoding();
? }
?
? ?//如果在当前容器中没有CharacterEncodingFilter类型的组件,那就执行下面的方法给你配置一个
? ?//这个就是说即使按需开启自动配置,也是以用户配置的优先
? ?@Bean
? ?@ConditionalOnMissingBean
? ?public CharacterEncodingFilter characterEncodingFilter() {
? ? ? ?CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
? ? ? ?filter.setEncoding(this.properties.getCharset().name());
? ? ? ?filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST));
? ? ? ?filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE));
? ? ? ?return filter;
? }
?
? ?@Bean
? ?public HttpEncodingAutoConfiguration.LocaleCharsetMappingsCustomizer localeCharsetMappingsCustomizer() {
? ? ? ?return new HttpEncodingAutoConfiguration.LocaleCharsetMappingsCustomizer(this.properties);
? }
?
? ?static class LocaleCharsetMappingsCustomizer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>, Ordered {
? ? ? ?private final Encoding properties;
?
? ? ? ?LocaleCharsetMappingsCustomizer(Encoding properties) {
? ? ? ? ? ?this.properties = properties;
? ? ? }
?
? ? ? ?public void customize(ConfigurableServletWebServerFactory factory) {
? ? ? ? ? ?if (this.properties.getMapping() != null) {
? ? ? ? ? ? ? ?factory.setLocaleCharsetMappings(this.properties.getMapping());
? ? ? ? ? }
?
? ? ? }
?
? ? ? ?public int getOrder() {
? ? ? ? ? ?return 0;
? ? ? }
? }
}
总结:
1、SpringBoot加载所有自动配置类
2、每个自动配置类按照条件加载生效
3、如果生效,配置类就会给容器中注册很多组件,这样功能就得以实现
4、用户【开发人员】配置了功能,就以用户的配置优先
5、而且很多自动配置类上面都应用了注解@EnableConfigurationProperties,将类属性和配置文件进行绑定,当对于自动配置的内容不满意时,可以自己在配置文件中进行修改或者想做到纯代码开发那就直接@Bean然后重写底层的方法,想换什么换什么
XXXAutoConfiguration -->>组件 -->> XXXproperties -->> application.properties,获取值的顺序
当需要修改自动配项时,要么去官网找Application Properties里面的不同场景,要么就直接底层找XXXAutoConfiguration,找@EnableConfigurationProperties注解,进入里面绑定的类的源码里查看前缀,然后自己在application.properties里面修改想修改的内容
|