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

本文涉及的产品
Elasticsearch Serverless通用抵扣包,测试体验金 200元
简介: 主要讲解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,当然,如果中途计划有变,再做调整。

相关实践学习
以电商场景为例搭建AI语义搜索应用
本实验旨在通过阿里云Elasticsearch结合阿里云搜索开发工作台AI模型服务,构建一个高效、精准的语义搜索系统,模拟电商场景,深入理解AI搜索技术原理并掌握其实现过程。
ElasticSearch 最新快速入门教程
本课程由千锋教育提供。全文搜索的需求非常大。而开源的解决办法Elasricsearch(Elastic)就是一个非常好的工具。目前是全文搜索引擎的首选。本系列教程由浅入深讲解了在CentOS7系统下如何搭建ElasticSearch,如何使用Kibana实现各种方式的搜索并详细分析了搜索的原理,最后讲解了在Java应用中如何集成ElasticSearch并实现搜索。 &nbsp;
相关文章
|
3月前
|
人工智能 Ubuntu 前端开发
Dify部署全栈指南:AI从Ubuntu配置到HTTPS自动化的10倍秘籍
本文档介绍如何部署Dify后端服务及前端界面,涵盖系统环境要求、依赖安装、代码拉取、环境变量配置、服务启动、数据库管理及常见问题解决方案,适用于开发与生产环境部署。
724 1
|
3月前
|
负载均衡 监控 Java
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
本文详细介绍了 Spring Cloud Gateway 的核心功能与实践配置。首先讲解了网关模块的创建流程,包括依赖引入(gateway、nacos 服务发现、负载均衡)、端口与服务发现配置,以及路由规则的设置(需注意路径前缀重复与优先级 order)。接着深入解析路由断言,涵盖 After、Before、Path 等 12 种内置断言的参数、作用及配置示例,并说明了自定义断言的实现方法。随后重点阐述过滤器机制,区分路由过滤器(如 AddRequestHeader、RewritePath、RequestRateLimiter 等)与全局过滤器的作用范围与配置方式,提
Spring Cloud Gateway 全解析:路由配置、断言规则与过滤器实战指南
|
3月前
|
Java 关系型数据库 MySQL
Spring Boot自动配置:魔法背后的秘密
Spring Boot 自动配置揭秘:只需简单配置即可启动项目,背后依赖“约定大于配置”与条件化装配。核心在于 `@EnableAutoConfiguration` 注解与 `@Conditional` 系列条件判断,通过 `spring.factories` 或 `AutoConfiguration.imports` 加载配置类,实现按需自动装配 Bean。
|
3月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
1242 0
|
2月前
|
监控 Java BI
《深入理解Spring》定时任务——自动化调度的时间管理者
Spring定时任务通过@Scheduled注解和Cron表达式实现灵活调度,支持固定频率、延迟执行及动态配置,结合线程池与异常处理可提升可靠性,适用于报表生成、健康检查等场景,助力企业级应用自动化。
|
2月前
|
前端开发 Java 应用服务中间件
《深入理解Spring》 Spring Boot——约定优于配置的革命者
Spring Boot基于“约定优于配置”理念,通过自动配置、起步依赖、嵌入式容器和Actuator四大特性,简化Spring应用的开发与部署,提升效率,降低门槛,成为现代Java开发的事实标准。
|
3月前
|
Java 测试技术 数据安全/隐私保护
通过yaml文件配置自动化测试程序
通过yaml文件可以将自动化测试环境,测试数据和测试行为分开,请看一下案例
113 4
|
3月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
576 5
|
3月前
|
jenkins Java 持续交付
使用 Jenkins 和 Spring Cloud 自动化微服务部署
随着单体应用逐渐被微服务架构取代,企业对快速发布、可扩展性和高可用性的需求日益增长。Jenkins 作为领先的持续集成与部署工具,结合 Spring Cloud 提供的云原生解决方案,能够有效简化微服务的开发、测试与部署流程。本文介绍了如何通过 Jenkins 实现微服务的自动化构建与部署,并结合 Spring Cloud 的配置管理、服务发现等功能,打造高效、稳定的微服务交付流程。
449 0
使用 Jenkins 和 Spring Cloud 自动化微服务部署
|
3月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
191 0
探索Spring Boot的@Conditional注解的上下文配置