乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • 第1章 Spring Boot 概述

    • 章节导读:Spring Boot概述与核心理念
    • Spring Boot是什么
    • Spring Boot与Spring Framework的关系
    • 约定优于配置
  • 第2章 快速入门与第一个应用

    • 章节导读:快速入门与第一个应用
    • SpringApplication
    • 第一个Spring Boot应用
  • 第3章 起步依赖与版本管理

    • 章节导读:起步依赖与版本管理
    • 起步依赖
    • BOM版本管理
  • 第4章 自动配置原理

    • 章节导读:自动配置原理
    • 自动配置原理
    • AutoConfigurationImportSelector
    • 自动配置报告
  • 第5章 核心注解

    • 章节导读:核心注解
    • @SpringBootApplication
    • @EnableAutoConfiguration
    • @ConditionalOnClass
    • @ConditionalOnMissingBean
    • @ConditionalOnBean
    • @ConditionalOnProperty
  • 第6章 外部化配置与属性绑定

    • 章节导读:外部化配置与属性绑定
    • 外部化配置
    • @ConfigurationProperties
    • @Value
    • 配置属性优先级
  • 第7章 Profile 与环境切换

    • 章节导读:Profile与环境切换
    • @Profile
    • 多环境配置文件
  • 第8章 内嵌服务器与部署

    • 章节导读:内嵌服务器与部署
    • 内嵌服务器
    • Fat Jar
  • 第9章 Actuator 与监控

    • 章节导读:Actuator与监控
    • Actuator Health
    • Actuator Info
    • Actuator Metrics
    • 自定义Endpoint
    • 自定义HealthIndicator
  • 第10章 开发工具与最佳实践

    • 章节导读:开发工具与最佳实践
    • Banner自定义
    • 热部署

一句话定位:"约定优于配置"是 Spring Boot 的灵魂设计哲学——框架通过内置的合理默认值,让开发者只在偏离约定时才写配置,从而将配置量从"全部手写"压缩到"仅覆盖例外"。


定义与作用

Convention over Configuration(约定优于配置) 是一种软件设计范式,主张框架应为常见场景提供默认的、合理的约定,开发者无需为这些默认行为显式编写配置,仅在需要偏离约定时才进行自定义。

它解决的痛点:

传统SSM场景需要手动配置的内容Spring Boot 的约定
数据源手动写 DataSource Bean,指定连接池类型、驱动类、URL、用户名、密码类路径存在 spring-jdbc + mysql-connector 时,自动创建 HikariCP 连接池,只需在 application.yml 填写连接参数
事务管理配置 DataSourceTransactionManager Bean,声明 <tx:annotation-driven>自动检测到 DataSource 时,自动创建 DataSourceTransactionManager,并开启 @Transactional 支持
Web MVC配置 InternalResourceViewResolver、RequestMappingHandlerMapping、静态资源映射自动配置 Spring MVC 全套组件,默认静态资源映射到 /static 和 /public
日志引入 log4j 或 logback,手写 logback.xml默认使用 logback + SLF4J,默认日志格式和级别已就绪,只需在 application.yml 调整 logging.level
服务器部署配置外部 Tomcat,调整 server.xml,打包 WAR内嵌 Tomcat 自动启动,默认端口 8080,直接 java -jar 运行

在飞翔科技的学生成绩管理系统中,小崔使用 Spring Boot 后,配置代码量从传统 SSM 的 200+ 行 XML 减少到不到 20 行 YAML。


适用位置与常用属性

"约定优于配置"不是注解,而是贯穿 Spring Boot 的设计原则。它体现在以下具体机制中:

体现机制约定内容如何覆盖约定
组件扫描默认扫描 @SpringBootApplication 所在包及其子包scanBasePackages 属性
配置文件默认读取 classpath:application.ymlspring.config.location 指定其他路径
数据源默认连接池 HikariCP,默认超时 30 秒spring.datasource.hikari.*
服务器默认内嵌 Tomcat,端口 8080server.port、server.servlet.context-path
日志默认 logback,INFO 级别,标准格式logging.level.*、logging.pattern.console
静态资源默认映射 /static、/public、/resources、/META-INF/resourcesspring.mvc.static-path-pattern
错误页面默认 /error 映射,Whitelabel 错误页自定义 ErrorController 或 ErrorAttributes
日期格式默认 Jackson 日期序列化为时间戳spring.jackson.date-format

核心原理

从"全配置"到"仅覆盖例外"的范式转换

约定的层级体系

层级解读:

  1. 硬编码默认值:Spring Boot 源码中定义了大量常量(如 server.port=8080),这是最低优先级的默认值。
  2. 自动配置类:根据 classpath 检测,自动注册 Bean 并应用默认值(如 HikariDataSource)。自动配置可以覆盖硬编码默认值。
  3. application.yml:开发者通过配置文件覆盖自动配置的默认值,这是日常开发中最常用的覆盖层。
  4. 命令行/环境变量:在生产环境中,运维人员通过环境变量或启动参数注入最终配置,优先级最高,覆盖一切。

白歌常说:"约定不是限制,而是帮你省掉 80% 的决策疲劳。当你需要偏离时,Spring Boot 给了你精确的手术刀。"


完整示例

场景说明

飞翔科技的学生成绩管理系统需要连接 MySQL 数据库 student_db。小崔对比了两种方案:传统 Spring 的"全配置" vs Spring Boot 的"约定覆盖"。

操作前:传统Spring的"全配置"方案

// 操作前:传统Java Config方式,需要手动声明每一个Bean
package com.feixiang.student.config;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;

@Configuration
@EnableTransactionManagement
public class DataSourceConfig {

    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/student_db?useUnicode=true&characterEncoding=utf-8");
        config.setUsername("root");
        config.setPassword("root");
        config.setDriverClassName("com.mysql.cj.jdbc.Driver");
        config.setMaximumPoolSize(10);
        config.setMinimumIdle(5);
        config.setConnectionTimeout(30000);
        config.setIdleTimeout(600000);
        config.setMaxLifetime(1800000);
        return new HikariDataSource(config);
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

问题:

  • 每个新项目都要写几乎一样的 DataSourceConfig。
  • HikariCP 参数硬编码,不同环境(dev/test/prod)需要多个配置类或复杂的 Profile 切换。
  • 连接池选型一旦变更(如从 HikariCP 切换到 Druid),需要改源码重新编译。

使用Spring Boot约定的完整代码

application.yml(仅写偏离约定的项):

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/student_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      maximum-pool-size: 10
      connection-timeout: 30000

主启动类:

package com.feixiang.student;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class StudentManagementApplication {
    public static void main(String[] args) {
        SpringApplication.run(StudentManagementApplication.class, args);
    }
}

业务代码直接使用 JdbcTemplate:

package com.feixiang.student.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

@Service
public class StudentService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    public String queryScore(String studentId) {
        String sql = "SELECT score FROM student WHERE id = ?";
        Integer score = jdbcTemplate.queryForObject(sql, Integer.class, studentId);
        return "学生 " + studentId + " 的成绩为:" + score;
    }
}

注意:这里没有 DataSourceConfig.java,没有 @Bean 方法声明 DataSource,没有 JdbcTemplate Bean 定义。Spring Boot 的自动配置已全部完成。

操作后运行结果及分析

启动应用后,控制台关键日志:

2024-05-20 09:20:15.456  INFO 12345 --- [main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
2024-05-20 09:20:15.678  INFO 12345 --- [main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed
2024-05-20 09:20:15.789  INFO 12345 --- [main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
2024-05-20 09:20:15.890  INFO 12345 --- [main] c.f.s.StudentManagementApplication       : Started in 2.123 seconds

分析:

  1. HikariPool 自动启动:DataSourceAutoConfiguration 检测到 spring-jdbc 和 HikariCP 在类路径,自动创建 HikariDataSource 并注入 application.yml 参数。
  2. JdbcTemplate 自动可用:JdbcTemplateAutoConfiguration 自动创建 JdbcTemplate Bean,开发者直接 @Autowired 使用。
  3. 事务管理器自动就绪:DataSourceTransactionManagerAutoConfiguration 自动创建事务管理器,支持 @Transactional(无需手动 @EnableTransactionManagement,Spring Boot 自动开启)。
  4. 配置量对比:传统方案约 60 行 Java Config + 数行 properties;Spring Boot 方案仅 10 行 YAML。

易错场景与面试考点

易错场景:误以为"约定优于配置"等于"完全不需要配置"

小崔曾犯过这样的错误:他以为 Spring Boot 什么都能自动猜出来,结果数据库连接报错。

错误示范:

# 错误:不写数据库配置,指望框架自动找到数据库
spring:
  application:
    name: student-management

启动报错:

***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class

原因分析:Spring Boot 的"约定"只覆盖通用基础设施的默认值(如连接池类型、日志格式、MVC 组件),但业务相关的连接参数(数据库地址、用户名、密码)不可能被猜出来。当开发者不配置 spring.datasource.url 时,Spring Boot 尝试寻找内嵌数据库(如 H2),如果也找不到,则启动失败。

正确做法:区分"框架能猜的"和"必须告诉它的"。

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/student_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

面试考点

Q:"约定优于配置"在 Spring Boot 中具体体现在哪些方面?举三个例子。

① 组件扫描:默认扫描启动类所在包及子包,无需手动指定 basePackages;② 数据源:类路径存在 spring-jdbc + 连接驱动时,自动创建 HikariCP 连接池,无需手写 DataSource Bean;③ 服务器:默认内嵌 Tomcat,端口 8080,无需 web.xml 和外部服务器部署。此外还包括日志默认使用 logback、静态资源默认映射到 /static 等。

Q:Spring Boot 的约定被覆盖时,优先级顺序是怎样的?

从高到低:命令行参数 > 环境变量 > SPRING_APPLICATION_JSON > 系统属性 > 各位置的 application.yml/application.properties > @PropertySource > SpringApplication 默认属性 > 源码硬编码默认值。共约 17 级,高优先级覆盖低优先级。

Q:如果团队约定使用 Druid 连接池而非 HikariCP,Spring Boot 还能保持"约定优于配置"吗?

可以。Spring Boot 的约定是可替换的。引入 druid-spring-boot-starter 后,该 Starter 中的自动配置类(如 DruidDataSourceAutoConfiguration)通过 @ConditionalOnMissingBean(DataSource.class) 检测到没有自定义 DataSource,就会创建 Druid 连接池。开发者只需引入依赖并在 application.yml 中配置 spring.datasource.druid.*,无需手写 DataSource Bean。这体现了"约定是可插拔的",而非"强制绑定"。

上一页
Spring Boot与Spring Framework的关系