2 -【 SpringBoot 配置方式 】- 3 自动配置原理

1 自动配置原理

1.1 SpringBoot 启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration

在这里插入图片描述

在这里插入图片描述

1.2 @EnableAutoConfiguration 作用

  • 利用 EnableAutoConfigurationImportSelector 给容器中导入一些组件?
  • 可以查看 selectImports() 方法的内容;
  • List configurations = getCandidateConfigurations(annotationMetadata, attributes); 获取候选的配置
    • SpringFactoriesLoader.loadFactoryNames() 扫描所有 jar 包类路径下 META‐INF/spring.factories 把扫描到的这些文件的内容包装成 properties对象 从 properties 中获取到 EnableAutoConfiguration.class类(类名)对应的值,然后把他们添加在容器中。

将 类路径下 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.cloud.CloudAutoConfiguration,\ 
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
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.CassandraRepositoriesAutoConfiguration ,\ 
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\ 
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration ,\ 
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\ 
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfi guration,\ 
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\ 
org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\ 
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\ 
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\ 
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\ 
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\ 
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\ 
org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\ 
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\ 
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.jest.JestAutoConfiguration,\ 
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\ 
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.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.flyway.FlywayAutoConfiguration,\ 
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\ 
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\ 
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\ 
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\ 
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.mobile.DeviceResolverAutoConfiguration,\ 
org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration, \ 
org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\ 
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\ 
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\ 
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\ 
org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\ 
org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\ 
org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\ 
org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\ 
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\ 
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\ 
org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\ 
org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\ 
org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\ 
org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\ 
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\ 
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.DispatcherServletAutoConfiguration,\ 
org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\ 
org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\ 
org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\ 
org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\ 
org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\ 
org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\ 
org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\ 
org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\ 
org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\ 
org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\ 
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration

每一个这样的 xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中;用他们来做自动配置;

第二级的注解@EnableAutoConfiguration,告诉 SpringBoot 基于你所添加的依赖,去“猜测”你想要如何配置 Spring。比如我们引入了 spring-boot-starter-web,而这个启动器中帮我们添加了 tomcatSpringMVC 的依赖。此时自动配置就知道你是要开发一个 web 应用,所以就帮你完成了 web 及 SpringMVC 的默认配置了!

总结,SpringBoot 内部对大量的第三方库或 Spring 内部库进行了默认配置,这些配置是否生效,取决于我们是否引入了对应库所需的依赖,如果有那么默认配置就会生效。

所以,我们使用 SpringBoot 构建一个项目,只需要引入所需框架的依赖,配置就可以交给 SpringBoot 处理了。除非你不希望使用 SpringBoot 的默认配置,它也提供了自定义配置的入口。

1.3 每一个自动配置类进行自动配置功能

1.4 以 HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理;

@Configuration   //表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件 
@EnableConfigurationProperties(HttpEncodingProperties.class)  //启动指定类的
ConfigurationProperties功能;将配置文件中对应的值和HttpEncodingProperties绑定起来;并把 HttpEncodingProperties加入到ioc容器中

@ConditionalOnWebApplication //Spring底层@Conditional注解(Spring注解版),根据不同的条件,如果 满足指定的条件,整个配置类里面的配置就会生效;    判断当前应用是否是web应用,如果是,当前配置类生效   

@ConditionalOnClass(CharacterEncodingFilter.class)  //判断当前项目有没有这个类
CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器;

@ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing =  true)  //判断配置文件中是否存在某个配置  spring.http.encoding.enabled;如果不存在,判断也是成立的 //即使我们配置文件中不配置pring.http.encoding.enabled=true,也是默认生效的;
public class HttpEncodingAutoConfiguration {
    //他已经和SpringBoot的配置文件映射了   
    private final HttpEncodingProperties properties; 
    //只有一个有参构造器的情况下,参数的值就会从容器中拿
    public HttpEncodingAutoConfiguration(HttpEncodingProperties properties) {
        this.properties = properties;
    }

    @Bean   //给容器中添加一个组件,这个组件的某些值需要从properties中获取          
    @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;
    }

根据当前不同的条件判断,决定这个配置类是否生效?

一但这个配置类生效;这个配置类就会给容器中添加各种组件;这些组件的属性是从对应的 properties 类中获取 的,这些类里面的每一个属性又是和配置文件绑定的;

1.5 所有在配置文件中能配置的属性都是在 xxxxProperties 类中封装者;配置文件能配置什么就可以参照某个功能对应的这个属性类

@ConfigurationProperties(prefix = "spring.http.encoding")  //从配置文件中获取指定的值和bean的属 性进行绑定 public class HttpEncodingProperties {
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF‐8");

精髓:

  • SpringBoot 启动会加载大量的自动配置类

  • 我们看我们需要的功能有没有 SpringBoot 默认写好的自动配置类;

  • 我们再来看这个自动配置类中到底配置了哪些组件;(只要我们要用的组件有,我们就不需要再来配置了)

  • 给容器中自动配置类添加组件的时候,会从 properties 类中获取某些属性。我们就可以在配置文件中指定这 些属性的值;

  • xxxxAutoConfigurartion:自动配置类;
    给容器中添加组件

  • xxxxProperties:封装配置文件中相关属性;

@Conditional 派生注解(Spring 注解版原生的 @Conditional 作用)

作用:必须是 @Conditional 指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生

@Conditional扩展注解作用(判断是否满足当前指定条件)
@ConditionalOnJava系统的java版本是否符合要求
@ConditionalOnBean容器中存在指定Bean;
@ConditionalOnMissingBean容器中不存在指定Bean;
@ConditionalOnExpression满足SpEL表达式指定
@ConditionalOnClass系统中有指定的类
@ConditionalOnMissingClass系统中没有指定的类
@ConditionalOnSingleCandidate容器中只有一个指定的Bean,或者这个Bean是首选Bean
@ConditionalOnProperty系统中指定的属性是否有指定的值
@ConditionalOnResource类路径下是否存在指定资源文件
@ConditionalOnWebApplication当前是web环境
@ConditionalOnNotWebApplication当前不是web环境
@ConditionalOnJndiJNDI存在指定项

自动配置类必须在一定的条件下才能生效;
我们怎么知道哪些自动配置类生效;
我们可以通过启用 debug=true属性;来让控制台打印自动配置报告,这样我们就可以很方便的知道哪些自动配置 类生效;

========================= 
AUTO‐CONFIGURATION REPORT
=========================

Positive matches:(自动配置类启用的)
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐ 

   DispatcherServletAutoConfiguration matched:
      ‐ @ConditionalOnClass found required class
'org.springframework.web.servlet.DispatcherServlet'; @ConditionalOnMissingClass did not find  unwanted class (OnClassCondition)       
      ‐ @ConditionalOnWebApplication (required) found StandardServletEnvironment  (OnWebApplicationCondition)

Negative matches:(没有启动,没有匹配成功的自动配置类)
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐

     ActiveMQAutoConfiguration:
            Did not match:
                      ‐ @ConditionalOnClass did not find required classes 'javax.jms.ConnectionFactory',  'org.apache.activemq.ActiveMQConnectionFactory' (OnClassCondition)
                            AopAutoConfiguration:
                                   Did not match:
                                             ‐ @ConditionalOnClass did not find required classes  'org.aspectj.lang.annotation.Aspect', 'org.aspectj.lang.reflect.Advice' (OnClassCondition) 

@ComponentScan

我们跟进源码:

在这里插入图片描述

并没有看到什么特殊的地方。我们查看注释:

在这里插入图片描述

大概的意思:

配置组件扫描的指令。提供了类似与<context:component-scan>标签的作用

通过basePackageClasses或者basePackages属性来指定要扫描的包。如果没有指定这些属性,那么将从声明这个注解的类所在的包开始,扫描包及子包

而我们的@SpringBootApplication注解声明的类就是main函数所在的启动类,因此扫描的包是该类所在包及其子包。因此,一般启动类会放在一个比较前的包目录中。

2 默认配置原理

2.1 默认配置类

通过刚才的学习,我们知道 @EnableAutoConfiguration 会开启 SpringBoot 的自动配置,并且根据你引入的依赖来生效对应的默认配置。那么问题来了:

  • 这些默认配置是在哪里定义的呢?
  • 为何依赖引入就会触发配置呢?

其实在我们的项目中,已经引入了一个依赖:spring-boot-autoconfigure,其中定义了大量自动配置类:

在这里插入图片描述

还有:

在这里插入图片描述

非常多,几乎涵盖了现在主流的开源框架,例如:

  • redis
  • jms
  • amqp
  • jdbc
  • jackson
  • mongodb
  • jpa
  • solr
  • elasticsearch

… 等等

我们来看一个我们熟悉的,例如 SpringMVC,查看 mvc 的自动配置类:

在这里插入图片描述

打开 WebMvcAutoConfiguration

在这里插入图片描述

我们看到这个类上的4个注解:

  • @Configuration:声明这个类是一个配置类

  • @ConditionalOnWebApplication(type = Type.SERVLET)

    ConditionalOn,翻译就是在某个条件下,此处就是满足项目的类是是Type.SERVLET类型,也就是一个普通web工程,显然我们就是

  • @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })

    这里的条件是OnClass,也就是满足以下类存在:Servlet、DispatcherServlet、WebMvcConfigurer,其中Servlet只要引入了tomcat依赖自然会有,后两个需要引入SpringMVC才会有。这里就是判断你是否引入了相关依赖,引入依赖后该条件成立,当前类的配置才会生效!

  • @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

    这个条件与上面不同,OnMissingBean,是说环境中没有指定的Bean这个才生效。其实这就是自定义配置的入口,也就是说,如果我们自己配置了一个WebMVCConfigurationSupport的类,那么这个默认配置就会失效!

接着,我们查看该类中定义了什么:

视图解析器:

在这里插入图片描述

处理器适配器(HandlerAdapter):

在这里插入图片描述

还有很多,这里就不一一截图了。

2.2 默认配置属性

另外,这些默认配置的属性来自哪里呢?

在这里插入图片描述
我们看到,这里通过 @EnableAutoConfiguration 注解引入了两个属性: WebMvcPropertiesResourceProperties。这不正是 SpringBoot 的属性注入玩法嘛。

我们查看这两个属性类:

在这里插入图片描述

找到了内部资源视图解析器的 prefixsuffix 属性。

ResourceProperties 中主要定义了静态资源(.js,.html,.css等)的路径:

在这里插入图片描述

如果我们要覆盖这些默认属性,只需要在application.properties中定义与其前缀prefix和字段名一致的属性即可。

3 总结

SpringBoot 为我们提供了默认配置,而默认配置生效的条件一般有两个:

  • 你引入了相关依赖
  • 你自己没有配置

1)启动器

所以,我们如果不想配置,只需要引入依赖即可,而依赖版本我们也不用操心,因为只要引入了 SpringBoot 提供的 stater(启动器),就会自动管理依赖及版本了。

因此,玩 SpringBoot 的第一件事情,就是找启动器,SpringBoot 提供了大量的默认启动器。

2)全局配置

另外,SpringBoot 的默认配置,都会读取默认属性,而这些属性可以通过自定义 application.properties 文件来进行覆盖。这样虽然使用的还是默认配置,但是配置中的值改成了我们自定义的。

因此,玩 SpringBoot 的第二件事情,就是通过 application.properties 来覆盖默认属性值,形成自定义配置。我们需要知道 SpringBoot 的默认属性 key。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不知所起 一往而深

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值