【Spring Boot系列3】自动化配置详解

简介: 主要讲解SpringBoot自动化配置原理,结合系列1的内容,可以形成SpringBoot原理知识体系闭环。SpringBoot只是个框架,前期我主要了解该框架内部的执行原理,然后掌握SpringBoot的基本使用姿势,就达到我的初步目标,后面打算结合公司具体的项目,然后再慢慢学习。

NNH~5GXWH[[SLR}N808NP09.jpg

主要讲解SpringBoot自动化配置原理,结合系列1的内容,可以形成SpringBoot原理知识体系闭环。

SpringBoot只是个框架,前期我主要了解该框架内部的执行原理,然后掌握SpringBoot的基本使用姿势,就达到我的初步目标,后面打算结合公司具体的项目,然后再慢慢学习。


基本介绍


一般认为,SpringBoot 微框架从两个主要层面影响 Spring 社区的开发者们:

  • 基于 Spring 框架的“约定优先于配置(COC)”理念以及最佳实践之路。
  • 提供了针对日常企业应用研发各种场景的 spring-boot-starter 自动配置依赖模块,如此多“开箱即用”的依赖模块,使得开发各种场景的 Spring 应用更加快速和高效。

我理解,一个就是去XML配置,一个就是自动化配置。

SpringBoot 提供的这些“开箱即用”的依赖模块都约定以 spring-boot-starter- 作为命名的前缀,常用的如下:

  • spring-boot-starter-logging
  • spring-boot-starter-web
  • spring-boot-starter-jdbc
  • spring-boot-starter-aop
  • spring-boot-starter-security
  • spring-boot-starter-actuator

并且皆位于 org.springframework.boot 包或者命名空间下(虽然 SpringBoot 的官方参考文档中提到不建议大家使用 spring-boot-starter- 来命名自己写的类似的自动配置依赖模块,但实际上,配合不同的 groupId,这不应该是什么问题)。

那么自动化配置,在SpringBoot的执行流程中处于哪个环节呢?它又是怎么自动化加载配置的呢?其实我们在之前的文章中,就可以找到部分答案。


知识回顾


@EnableAutoConfiguration

在文章《【Spring Boot系列1】一文带你了解Spring Boot(上)》,我们介绍过@EnableAutoConfiguration注解,@EnableAutoConfiguration 是借助 @Import 的帮助,将所有符合条件的 @Configuration 配置都加载到当前 SpringBoot 创建并使用的 IoC 容器,就跟一只“八爪鱼”一样:

image.gifHO3%[DT95BIXMS3J}Q25UQH.png


执行流程

在文章《【Spring Boot系列1】一文带你了解Spring Boot(下)》,我们讲解了SpringApplication.run执行流程,第9步描述“最核心的一步,将之前通过 @EnableAutoConfiguration 获取的所有配置以及其他形式的 IoC 容器配置加载到已经准备完毕的 ApplicationContext。”

所以自动化配置就是在“创建好上下文”之后,在“通知应用装载上下文”之前进行的,它做了啥事情呢?其实就是将自动化配置信息完善到上下文中,而这个自动加载的过程,主要就靠@EnableAutoConfiguration。所以你也可以理解,通过该注解给Spring提供一个完善的上下文环境。

这里讲述了自动化配置的执行位置、执行方式、执行后的结果,那最后执行依赖的形式是什么呢?具体有啥用呢?大家可能还是觉得有些抽象,举个栗子:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>

大白话概括一下,其实就是把这些东东加载到SpringBoot中,方便大家使用,比如jdbc、web、log、security等等,我把他们理解为“扩展功能”,感觉更贴切一些,支持“自动加载”和“开箱即用”。


自动化配置


自动化配置流程

  1. SpringBoot启动的时候加载主配置类,开启了自动配置功能 @EnableAutoConfiguration;
  2. @EnableAutoConfiguration中使用了 @Import({AutoConfigurationImportSelector.class})向容器中添加了一些组件(自动配置类):
  • 扫描所有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
  1. 每一个这样的xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中,用他们来做自动配置。

盗用网上的一副图,感觉画的挺好的,就是有点大,建议大家在电脑上看:

image.gif_SL%_@00WSD~2GA(5_J)N79.png

mybatis-spring-boot-starter、spring-boot-starter-web等组件的META-INF文件下均含有spring.factories文件,自动配置模块中,SpringFactoriesLoader收集到文件中的类全名并返回一个类全名的数组,返回的类全名通过反射被实例化,就形成了具体的工厂实例,工厂实例来生成组件具体需要的bean。


原理分析

以HttpEncodingAutoConfiguration为例,就是以前在web.xml中配置的CharacterEncodingFilter过滤器:

//表示这是一个配置类,相当于以前编写的Spring配置文件
@Configuration
//启用HttpProperties类的ConfigurationProperties功能,通过配置文件为属性注入值,并将其添加到容器中
@EnableConfigurationProperties({HttpProperties.class})
//当该应用是web应用时才生效
@ConditionalOnWebApplication(type = Type.SERVLET)
//必须包含CharacterEncodingFilter类才生效
@ConditionalOnClass({CharacterEncodingFilter.class})
//如果配置文件中有spring.http.encoding选项则该配置生效,否则不生效。但是默认已经生效了
@ConditionalOnProperty(prefix = "spring.http.encoding",value = {"enabled"},matchIfMissing = true)
public class HttpEncodingAutoConfiguration {
    private final Encoding properties;
    //将容器中的HttpProperties注入
    public HttpEncodingAutoConfiguration(HttpProperties properties) {
        this.properties = properties.getEncoding();
    }
    //将返回的filter添加到容器中,作为bean
    @Bean
    //如果容器中没有这个bean才会生效
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.autoconfigure.http.HttpProperties.Encoding.Type.RESPONSE));
        return filter;
    }
}
//从配置文件中获取指定的值,然后绑定到指定的属性值
@ConfigurationProperties(
    prefix = "spring.http"
)
public class HttpProperties {
    private Charset charset;
    private Boolean force;
    private Boolean forceRequest;
    private Boolean forceResponse;
    private Map<Locale, Charset> mapping;
}

注意:

  • 根据当前情况进行判断,决定配置类是否生产,如果不满足条件自动配置就不会生效
  • 自动配置类xxAutoConfiguration的属性是从对应的xxProperties类中获取
  • xxProperties类中的信息是通过配置文件注入绑定的,可以通过配置文件指定属性的值

自动配置类必须在一定的条件下才能生效,我们怎么知道哪些自动配置类生效,我们可以通过启用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)

简单总结一下:

  • SpringBoot在启动时会加载大量的自动配置类
  • 通过自动配置了向容器中添加组件
  • 通过这些组件自动完成许多功能,从而简化配置


SpringBoot全流程总结


为了让大家形成知识闭环,我将之前的SpringBoot执行流程整体,通过几幅图再整体串一下:

image.gif6NR8HV(WE()[8E0(UT42K]B.jpg

什么?图片字体太小,看不清楚?那我放大一下。

构建SpringApplication:R3BM(JV(Z1AWZC1(ELSI$W4.png

启动SpringApplication:

W([M)30`2ZJRT6LPPDE~@3H.png

自动化配置加载:

A@T%3QACBBDQA8C_NAKH9M6.png

如果还是看不清楚,就在电脑上看吧,楼哥也没办法。

上图为SpringBoot启动结构图:

  • 构建SpringApplication:进行SpringApplication的初始化模块,配置一些基本的环境变量、资源、构造器、监听器
  • 启动SpringApplication:实现了应用具体的启动方案,包括启动流程的监听模块、加载配置环境模块、及核心的创建上下文环境模块
  • 自动化配置加载:是自动化配置模块,该模块作为springboot自动配置核心,在后面的分析中会详细讨论。

前面知识的更多细节,请参考《【Spring Boot系列1】一文带你了解Spring Boot(上)》、《【Spring Boot系列1】一文带你了解Spring Boot(下)》两文。


后记


上面需要总结的知识,基本都已经总结过了,这里就写点水文吧。


后面打算花些时间,仔细研读《JAVA编程思想》和《深入理解Java虚拟机》这两本书,开启Java学习的第二个阶段--进阶阶段!到时也给自己列个详细的Plan,当然,如果中途计划有变,再做调整。

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
1月前
|
XML Java 测试技术
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
121 26
|
3月前
|
Java Spring
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
185 73
|
4月前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
84 0
|
2月前
|
XML Java 应用服务中间件
Spring Boot 两种部署到服务器的方式
本文介绍了Spring Boot项目的两种部署方式:jar包和war包。Jar包方式使用内置Tomcat,只需配置JDK 1.8及以上环境,通过`nohup java -jar`命令后台运行,并开放服务器端口即可访问。War包则需将项目打包后放入外部Tomcat的webapps目录,修改启动类继承`SpringBootServletInitializer`并调整pom.xml中的打包类型为war,最后启动Tomcat访问应用。两者各有优劣,jar包更简单便捷,而war包适合传统部署场景。需要注意的是,war包部署时,内置Tomcat的端口配置不会生效。
328 17
Spring Boot 两种部署到服务器的方式
|
2月前
|
监控 Java 数据库连接
Spring c3p0配置详解
在Spring项目中配置C3P0数据源,可以显著提高数据库连接的效率和应用程序的性能。通过合理的配置和优化,可以充分发挥C3P0的优势,满足不同应用场景的需求。希望本文的详解和示例代码能为开发者提供清晰的指导,帮助实现高效的数据库连接管理。
82 10
|
3月前
|
Java Spring
【Spring配置相关】启动类为Current File,如何更改
问题场景:当我们切换类的界面的时候,重新启动的按钮是灰色的,不能使用,并且只有一个Current File 项目,下面介绍两种方法来解决这个问题。
|
3月前
|
Java Spring
【Spring配置】idea编码格式导致注解汉字无法保存
问题一:对于同一个项目,我们在使用idea的过程中,使用汉字注解完后,再打开该项目,汉字变成乱码问题二:本来a项目中,汉字注解调试好了,没有乱码了,但是创建出来的新的项目,写的注解又成乱码了。
|
3月前
|
Java Spring
【Spring配置】创建yml文件和properties或yml文件没有绿叶
本文主要针对,一个项目中怎么创建yml和properties两种不同文件,进行配置,和启动类没有绿叶标识进行解决。
|
3月前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
204 14
|
3月前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
80 6