当前位置: 首页 > news >正文

怎么理解 Spring Boot 的约定优于配置 ?

在传统的 Spring 开发中,大家可能都有过这样的经历:项目还没开始写几行核心业务代码,就已经在各种配置文件中耗费了大量时间。比如,要配置数据库连接,不仅要在 XML 文件里编写冗长的数据源配置,还要处理事务管理连接池配置等;搭建 Web 项目时,从配置 DispatcherServlet 到配置各种视图解析器,再到处理静态资源路径,每一步都需要小心翼翼地编写配置代码,稍有不慎就可能导致启动失败或功能异常。

二、什么是约定优于配置

“约定优于配置”(Convention over Configuration),也称作按约定编程,是一种软件设计范式,旨在减少软件开发人员需做出决定的数量,获得简单的好处,而又不失灵活性 。简单来说,就是框架通过一些默认的约定,帮我们预先设置好大部分通用的配置,开发者只需在少数不符合约定的情况下,才需要进行额外的配置工作。

举个生活中的例子,我们去餐厅吃饭,一般餐厅都会有默认的餐具摆放方式和点餐流程。如果没有特殊要求,我们就按照餐厅的 “约定” 来用餐,比如使用摆在桌上的筷子、勺子,在菜单上勾选菜品等。只有当我们有特殊需求,比如想要一次性手套代替筷子,或者需要额外的调料时,才需要向服务员提出 “配置” 要求。这就好比在 Spring Boot 开发中,框架已经为我们设定好了项目结构、依赖管理、配置文件加载等方面的约定,大部分情况下我们无需额外配置,只有在个别特殊场景下,才需要手动调整配置。

在 Spring Boot 中,“约定优于配置” 是其核心设计理念之一,它贯穿于整个框架的使用过程中。通过遵循这些约定,开发者能够快速搭建起一个功能完备的 Spring 应用,无需花费大量时间和精力在繁琐的配置工作上,从而将更多的注意力集中在业务逻辑的实现上,极大地提升了开发效率

三、传统开发与 Spring Boot 对比

(一)传统 Spring 开发的配置痛点

在传统的 Spring 开发模式下,开发者往往要面对诸多繁杂的配置工作,这些配置工作不仅耗时费力,还容易出错,严重影响开发效率。

管理 jar 包依赖就是一项让人头疼的任务。在传统 Spring 项目中,我们需要手动引入项目所需的各种 jar 包,并且要确保各个 jar 包之间的版本兼容性 。一旦出现版本冲突,排查和解决问题就会变得异常困难。比如,在一个包含 Spring MVC、Spring Data JPA 和 Spring Security 等多个模块的项目中,需要引入大量相关的 jar 包,每个 jar 包可能又依赖其他的子 jar 包,稍有不慎就可能导致依赖冲突,像不同版本的 Spring 核心库之间的冲突,会引发各种难以调试的错误。

维护 web.xml 和 Dispatch - Servlet.xml 等配置文件也是一大痛点。在 web.xml 中,我们要配置 Servlet、Filter、Listener 等组件,定义它们的初始化参数、映射路径等 。例如,配置一个简单的 DispatcherServlet,就需要在 web.xml 中编写如下代码:

<servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc - servlet.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

而在 Dispatch - Servlet.xml(通常是 springmvc - servlet.xml)中,又要配置视图解析器、处理器映射器、处理器适配器等 Spring MVC 的核心组件 。配置视图解析器时,可能需要类似这样的配置:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB - INF/views/"/><property name="suffix" value=".jsp"/>
</bean>

随着项目规模的增大,这些配置文件会变得越来越臃肿,维护成本也越来越高。而且,不同的配置项之间可能存在复杂的依赖关系,修改一处配置可能会影响到其他部分的功能,这使得配置的管理变得非常困难。

(二)Spring Boot 如何简化配置

Spring Boot 通过引入自动配置默认约定,彻底改变了这种繁琐的开发局面,让开发者能够从配置的泥潭中解脱出来,专注于业务逻辑的实现。

在依赖管理方面,Spring Boot 引入了 Starter 的概念 。Starter 是一组预定义的依赖集合,它将项目开发中常用的依赖进行了整合和封装。比如,当我们开发一个 Spring Boot Web 应用时,只需要在 pom.xml 文件中添加 spring-boot-starter-web 依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot 会自动管理该 Starter 所依赖的所有 jar 包版本,包括 Spring MVC、Tomcat(嵌入式 Servlet 容器)等相关依赖,无需我们手动去指定每个 jar 包的版本,大大减少了版本冲突的可能性 。

对于配置文件 ,Spring Boot 有一套默认的约定 。它默认加载 application.properties 或 application.yml 文件作为配置文件,并且对很多配置项都提供了默认值。例如,默认的 Web 服务器端口是 8080,如果我们没有在配置文件中指定端口号,应用就会使用这个默认端口启动 。在数据库连接配置方面,Spring Boot 也提供了默认的数据源配置,如果我们使用的是常见的数据库(如 MySQL、Oracle 等),只需要在配置文件中简单地配置数据库的连接信息,如用户名、密码、URL 等,Spring Boot 就会自动帮我们创建数据源和相关的数据库连接配置。例如,在 application.properties 中配置 MySQL 连接:

spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

Spring Boot 会根据这些配置自动创建数据源,并将其注入到 Spring 容器中,供其他组件使用 .Spring Boot 还通过自动配置机制,根据项目中引入的依赖和配置文件,自动创建和配置 Spring 容器中的各种 Bean 。

例如,当我们引入了 spring-boot-starter-web 依赖后,Spring Boot 会自动配置 DispatcherServlet、视图解析器、处理器映射器等 Spring MVC 的核心组件,无需我们再像传统 Spring 开发那样在 XML 文件中进行繁琐的配置 。这一切都是基于 Spring Boot 的自动配置类和条件注解(如 @ConditionalOnClass、@ConditionalOnProperty 等)实现的,这些条件注解会根据类路径下是否存在某个类、配置文件中是否存在某个属性等条件来决定是否创建和配置某个 Bean。

 

(三)Starter 依赖机制

Starter 是 Spring Boot 的一项重要特性,它极大地简化了项目的依赖管理 。Spring Boot 将各种常见的应用场景封装成一个个的 Starter,每个 Starter 都是一组相关的依赖集合 。例如,spring-boot-starter-web是用于开发 Web 应用的 Starter,它包含了 Spring MVC、Tomcat(嵌入式 Servlet 容器)等相关依赖;spring-boot-starter-data-jpa是用于开发 JPA(Java Persistence API)数据访问层的 Starter,它包含了 Spring Data JPA、Hibernate 等相关依赖 。

当我们在项目中添加某个 Starter 依赖时,只需要在pom.xml(Maven 项目)或build.gradle(Gradle 项目)文件中添加相应的依赖坐标,Spring Boot 会自动管理该 Starter 所依赖的所有 jar 包版本,避免了手动管理依赖版本带来的麻烦 。例如,在 Maven 项目中添加spring-boot-starter-web依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

添加这个依赖后,Spring Boot 会自动引入 Spring MVC、Tomcat 等相关的 jar 包,并且会根据项目的需要自动配置好这些组件 。我们无需关心这些组件之间的依赖关系和版本兼容性,只需要专注于业务逻辑的开发 。这种方式不仅减少了配置工作量,还降低了因依赖冲突导致的问题发生概率 。

(四)自动装配机制

Spring Boot 的自动装配机制是 “约定优于配置” 理念的核心体现之一 。它通过扫描类路径下的META-INF/spring.factories文件自动配置 Spring 容器中的 Bean

在每个 Spring Boot Starter 的 META-INF/spring.factories 文件中,定义了一系列的自动配置类 。例如,spring-boot-starter-web的spring.factories文件中定义了WebMvcAutoConfiguration等自动配置类,这些配置类负责创建和配置 Spring MVC 相关的 Bean,如DispatcherServlet、HandlerMapping、ViewResolver等 。当我们在项目中引入spring-boot-starter-web依赖后,Spring Boot 在启动时会扫描META-INF/spring.factories文件,找到与WebMvcAutoConfiguration相关的配置,并根据项目的实际情况(如是否存在相关的类、配置文件中的属性等)决定是否创建和配置这些 Bean 。

自动装配的核心原理是基于 Spring 的条件注解@ConditionalOnClass@ConditionalOnProperty等 。@ConditionalOnClass表示只有当类路径下存在某个类时,才会创建和配置相关的 Bean;@ConditionalOnProperty表示只有当配置文件中存在某个属性时,才会创建和配置相关的 Bean 。例如,WebMvcAutoConfiguration类上使用了@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })注解,这意味着只有当类路径下存在Servlet、DispatcherServlet和WebMvcConfigurer这三个类时,才会创建和配置 Spring MVC 相关的 Bean 。通过这种方式,Spring Boot 实现了根据项目的依赖和配置自动创建和配置 Bean,大大减少了开发者手动配置的工作量 。

        

 

四、优势

(一)提高开发效率

在传统的 Spring 开发中,开发者花费大量时间在各种配置文件的编写和调试上,往往项目还未开始核心业务开发,就已经被配置工作搞得疲惫不堪。而 Spring Boot 的 “约定优于配置” 理念,就像是为开发者打造了一条高速公路,让开发过程变得顺畅无阻。

以搭建一个简单的 Web 应用为例,在传统 Spring 开发中,光是配置 DispatcherServlet、视图解析器、各种过滤器等,就需要编写大量的 XML 配置代码,并且要确保各个配置项之间的逻辑关系正确无误。而在 Spring Boot 中,我们只需要引入spring-boot-starter-web依赖,Spring Boot 就会自动帮我们完成这些配置工作,开发者可以在短短几分钟内就搭建好一个基本的 Web 应用框架,迅速投入到业务逻辑的开发中。这种方式大大减少了配置时间,让开发效率得到了质的飞跃。

(二)增强代码的可维护性

统一的约定使得 Spring Boot 项目的结构和配置更加清晰、规范 。在一个遵循 Spring Boot 约定的项目中,团队成员可以很容易地找到他们需要的代码和配置文件。例如,按照约定的项目结构,控制器层的代码位于controller包下,服务层的代码位于service包下,数据访问层的代码位于repository包下,配置文件位于resources目录下。这种清晰的结构使得代码的可读性大大提高,当需要修改或扩展某个功能时,开发者可以快速定位到相关的代码和配置。

而且,由于大部分配置都是由框架自动完成的,开发者只需要关注自己的业务逻辑和少量的特殊配置,减少了配置文件中冗余和复杂的配置项,降低了配置出错的概率 。当项目规模逐渐增大时,这种优势更加明显,能够有效降低维护成本,提高项目的可维护性。

(三)促进团队协作

在团队开发中,一致的约定就像是一套通用的语言,让团队成员之间的沟通和协作变得更加顺畅 。如果每个成员都按照自己的方式进行配置和开发,那么在代码合并和集成时,很容易出现各种问题,比如配置冲突、依赖版本不一致等。而 Spring Boot 的 “约定优于配置”,让团队成员遵循相同的规则进行开发,减少了因配置差异而产生的问题 。

例如,在一个多人开发的 Spring Boot 项目中,大家都使用默认的配置文件格式和位置,按照约定的项目结构进行代码组织。这样,新加入的成员可以快速熟悉项目的结构和配置方式,融入团队开发中 。在进行代码审查时,也更容易理解其他成员的代码逻辑,提高了团队协作的效率,有利于项目的顺利推进

相关文章:

怎么理解 Spring Boot 的约定优于配置 ?

在传统的 Spring 开发中&#xff0c;大家可能都有过这样的经历&#xff1a;项目还没开始写几行核心业务代码&#xff0c;就已经在各种配置文件中耗费了大量时间。比如&#xff0c;要配置数据库连接&#xff0c;不仅要在 XML 文件里编写冗长的数据源配置&#xff0c;还要处理事务…...

Dify 是什么?Dify是一个开源的LLM应用开发平台,支持快速搭建生成式AI应用,具有RAG管道、Agent功能、模型集成等特点

首先&#xff0c;Dify是一个开源的LLM应用开发平台&#xff0c;支持快速搭建生成式AI应用&#xff0c;具有RAG管道、Agent功能、模型集成等特点75。根据搜索结果&#xff0c;网页6详细对比了多个RAG和AI开发框架&#xff0c;包括MaxKB、FastGPT、RagFlow、Anything-LLM等。其中…...

数据预处理都做什么,用什么工具

数据预处理是数据分析、数据挖掘和机器学习中的关键步骤&#xff0c;其目的是将原始数据转换为适合后续分析或建模的格式。以下是关于数据预处理的主要内容及常用工具的详细介绍&#xff1a; 一、数据预处理的主要任务 数据预处理的主要任务包括以下几个方面&#xff1a; 数据…...

windows蓝牙驱动开发-在蓝牙配置文件驱动程序中接受 L2CAP 连接

L2CAP 服务器配置文件驱动程序会响应来自远程设备的传入逻辑链接控制和适应协议 (L2CAP) 连接请求。 例如&#xff0c;PDA 的 L2CAP 服务器配置文件驱动程序将响应来自 PDA 的传入连接请求。 接收传入 L2CAP 连接请求 1. 若要接收来自特定 PSM 的任何远程设备的传入 L2CAP 连…...

【原理图PCB专题】自制汉字转码工具,适配Allgero 17版本 Skill

众所周知,在使用Skill来编写Allegro控制脚本时如果程序的源码里是汉字,那么有可能会出现乱码。比如像下图这样的程序: 在Allegro中运行如下图所示: 那么如果我们需要让他转成正常的中文字符,就需要将字符转成GBK编码 打开自制小软件:中文与GBK编码互转V1…...

欧拉公式在信号处理中的魔法:调幅信号的生成与频谱分析

欧拉公式在信号处理中的魔法:调幅信号的生成与频谱分析 “数学不是枯燥的符号,而是宇宙的诗歌。” 当我们用欧拉公式解开调幅信号的频谱密码时,仿佛看到电磁波在时空中跳动的频率之舞。这篇博客将带你亲手触摸信号处理中的数学之美。 一、当欧拉公式遇见调幅信号:一场数学与…...

如何在Ubuntu中切换多个PHP版本

在Ubuntu环境下实现PHP版本的灵活切换&#xff0c;是众多开发者与系统管理员的重要技能之一。下面&#xff0c;我们将深入探讨如何在Ubuntu系统中安装、配置及管理多个PHP版本&#xff0c;确保您的开发环境随心所欲地适应各类项目需求。 开始前的准备 确保您的Ubuntu系统保持…...

基于opencv的HOG+角点匹配教程

1. 引言 在计算机视觉任务中&#xff0c;特征匹配是目标识别、图像配准和物体跟踪的重要组成部分。本文介绍如何使用 HOG&#xff08;Histogram of Oriented Gradients&#xff0c;方向梯度直方图&#xff09; 和 角点检测&#xff08;Corner Detection&#xff09; 进行特征匹…...

Linux线程概念与线程操作

Linux线程概念与线程操作 线程概念 前面提到进程程序代码和数据进程结构体&#xff0c;在线程部分就需要进一步更新之前的认识 进程实际上承担分配系统资源的基本实体&#xff0c;而线程是进程中的一个执行分支&#xff0c;是操作系统调度的基本单位 此处需要注意&#xff0…...

AI软件栈:LLVM分析(五)

数据流分析是编译优化、代码生成的关键理论。其数学基础是离散数学中的半格(Semi-Lattice)和格。半格与格不仅是编译优化和代码生成的重要理论基础,也是程序分析、验证及自动化测试的系统理论基础。 文章目录 格、半格与不动点格、半格与不动点 半格是指针对二元组 < S …...

Git指南-从入门到精通

代码提交和同步命令 流程图如下&#xff1a; 第零步: 工作区与仓库保持一致第一步: 文件增删改&#xff0c;变为已修改状态第二步: git add &#xff0c;变为已暂存状态 bash $ git status $ git add --all # 当前项目下的所有更改 $ git add . # 当前目录下的所有更改 $ g…...

Linux 文件系统挂载

系列文章目录 Linux内核学习 Linux 知识&#xff08;1&#xff09; Linux 知识&#xff08;2&#xff09; WSL Ubuntu QEMU 虚拟机 Linux 调试视频 PCIe 与 USB 的补充知识 vscode 使用说明 树莓派 4B 指南 设备驱动畅想 Linux内核子系统 Linux 文件系统挂载 文章目录 系列文章…...

Qt QSpinBox 总结

Qt5 QSpinBox 总结 1. 基本特性 用途&#xff1a;用于输入和调整整数值&#xff0c;支持通过上下箭头、键盘输入或编程方式修改值。 默认范围&#xff1a;0 到 99&#xff0c;可通过 setRange(min, max) 自定义。 步长控制&#xff1a;setSingleStep(step) 设置单步增减值&a…...

【OJ项目】深入剖析题目接口控制器:功能、实现与应用

《深入剖析题目接口控制器&#xff1a;功能、实现与应用》 一、引言 在在线编程平台或竞赛系统中&#xff0c;题目管理和提交是核心功能之一。QuestionController 类作为控制器层&#xff0c;承担着处理与题目相关的各种请求的重要职责&#xff0c;包括题目的增删改查、题目提…...

周考考题(学习自用)

1.查询student表中name叫张某的信息 select * from student where name张某; 2.写出char和varchar类型的区别 1&#xff09;char存储固定长度的字符串&#xff0c;varchar存储可变长度的字符串&#xff08;在实际长度的字符串上加上一个字节用于存储字符串长度&#xff09;&a…...

【matlab】大小键盘对应的Kbname

matlab中可以通过Kbname来识别键盘上的键。在写范式的时候&#xff0c;遇到一个问题&#xff0c;我想用大键盘上排成一行的数字按键评分&#xff0c;比如 Kbname(1) 表示键盘上的数字1&#xff0c;但是这种写法只能识别小键盘上的数字&#xff0c;无法达到我的目的&#xff0c;…...

LabVIEW与小众设备集成

在LabVIEW开发中&#xff0c;当面临控制如布鲁克OPUS红外光谱仪这类小众专业设备的需求&#xff0c;而厂家虽然提供了配套软件&#xff0c;但由于系统中还需要控制其他设备且不能使用厂商的软件时&#xff0c;必须依赖特定方法通过LabVIEW实现设备的控制。开发过程中&#xff0…...

Android 系统Service流程

主要用到的源码文件 /frameworks/base/core/java/android/app/ContextImpl.java 和ams通信。 /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java 初始化Service,.管理服务 ActiveServices对象mServices /frameworks/base/services/core/…...

Gartner预测2025年网络安全正在进入AI动荡时期:软件供应链和基础设施技术堆栈中毒将占针对企业使用的人工智能恶意攻击的 70% 以上

Gartner 预测&#xff0c;网络安全正在进入 AI 动荡时期。安全和风险管理领导者必须根据早期生成式 AI 部署的失败以及 AI 代理清洗来评估即将到来的 AI 进展。 主要发现 随着各大企业开展大量人工智能采用和开发项目&#xff0c;应用安全弱点的暴露程度不断提高&#xff0c;包…...

华为最新OD机试真题-最长子字符串的长度(一)-Python-OD统一考试(E卷)

最新华为OD机试考点合集:华为OD机试2024年真题题库(E卷+D卷+C卷)_华为od机试题库-CSDN博客 每一题都含有详细的解题思路和代码注释,精编c++、JAVA、Python三种语言解法。帮助每一位考生轻松、高效刷题。订阅后永久可看,发现新题及时跟新。 题目描述: 给你一个字符串…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

深入理解 React 样式方案

React 的样式方案较多,在应用开发初期,开发者需要根据项目业务具体情况选择对应样式方案。React 样式方案主要有: 1. 内联样式 2. module css 3. css in js 4. tailwind css 这些方案中,均有各自的优势和缺点。 1. 方案优劣势 1. 内联样式: 简单直观,适合动态样式和…...

虚幻基础:角色旋转

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录 移动组件使用控制器所需旋转&#xff1a;组件 使用 控制器旋转将旋转朝向运动&#xff1a;组件 使用 移动方向旋转 控制器旋转和移动旋转 缺点移动旋转&#xff1a;必须移动才能旋转&#xff0c;不移动不旋转控制器…...