SpringBoot---自动配置【快乐的源码】

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 {}

 

 


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里面修改想修改的内容

 

 

在使用中:

  • 当想要进行某些场景开发,那就首先引入场景依赖,spring-boot-starter-XXX

  • 在场景开发过程中,需要查看某些自动配置

  • 一个是自己去spring-boot-autoconfigure-2.6.1.jar这个依赖里面找对应的引入的场景的自动配置类,看看都配置了什么

  • 另一个直接在application.properties配置文件中写上 debug=true,就能在输出中看见,有哪些自动配置启动生效了,那些没生效,因为什么 Negative matches:不生效的 Positive matches: 生效了的

  • 假如在开发时对有些配置不喜欢,想要修改配置:

  • 要么就在官网里面找ApplicationProperties里面找自己开发的那个场景相应的配置或者自己去spring-boot-autoconfigure-2.6.1.jar依赖里面找对应场景的自动配置类,看都有哪些配置属性和配置文件绑定了

  • 要么就自己@Bean给容器中添加底层组件,用户有的,会优先用户的。

  • 例如现在想要修改SpringBoot启动时的动画。找到官网的配置项里面的coreproperties,在里面有一个spring.banner,在这个配置里面对应设置动画的就是[spring.banner.image.location],配置项后面也有解释说什么可以用,在配置文件中设置他的路径,一般这个图片和配置文件放在同一个目录下

 

 

 

 

 

 

 

 

 

posted @ 2021-12-06 22:12  优质水  阅读(116)  评论(0)    收藏  举报