Spring 框架的历史与动机
2003 年,Rod Johnson 发布了 Spring Framework 1.0,其动机是解决 Java EE(当时叫 J2EE)中 EJB(Enterprise JavaBeans)的极度复杂性。EJB 要求开发者实现多个接口、编写大量部署描述符 XML、依赖应用服务器容器,一个简单的业务逻辑组件往往需要数十行样板代码。
Spring 的核心理念是:用普通 Java 对象(POJO)编写业务逻辑,由框架负责管理对象的生命周期和依赖关系。这种轻量级的设计大幅降低了 Java 企业应用的开发门槛。随着时间推移,Spring 生态系统不断扩大,但配置本身变得繁琐——几十个 XML 文件、大量 @Bean 配置类成为新的痛点。
2014 年,Spring Boot 1.0 发布,其核心理念是"约定优于配置"(Convention over Configuration)。Spring Boot 通过自动配置机制,使开发者只需少量注解和配置即可快速启动一个生产就绪的应用。Spring Boot 3.x 基于 Spring Framework 6.x,要求 Java 17+,原生支持 GraalVM 本机编译。
核心概念名词解释
IoC 容器与依赖注入详解
理解 IoC 最好的方式是对比"传统方式"和"IoC 方式"。假设 OrderService 需要使用 UserService:
传统方式(紧耦合)
- OrderService 内部 new UserService()
- OrderService 与 UserService 强绑定
- 无法替换为 MockUserService
- 难以独立测试 OrderService
IoC 方式(松耦合)
- OrderService 声明需要 UserService
- 容器注入具体实现
- 测试时可注入 MockUserService
- 各组件可独立替换
三种注入方式
Spring 支持三种依赖注入方式,官方和社区均推荐构造器注入,因为它能保证依赖不可变、便于测试,且能在启动时暴露循环依赖问题。
// ✅ 推荐:构造器注入(依赖不可变,便于测试)
@Service
public class OrderService {
private final UserService userService;
private final OrderRepository orderRepository;
// Spring 自动注入,单个构造器无需 @Autowired
public OrderService(UserService userService, OrderRepository orderRepository) {
this.userService = userService;
this.orderRepository = orderRepository;
}
}
// ⚠️ 不推荐:字段注入(隐藏依赖,难以测试)
@Service
public class OrderService {
@Autowired
private UserService userService; // 字段注入
}
Spring Boot 自动配置原理
Spring Boot 的"魔法"来源于自动配置机制。当你在 pom.xml 中添加 spring-boot-starter-web 时,Spring Boot 会自动配置好 Tomcat、Jackson、DispatcherServlet 等一系列组件,无需手动声明任何 Bean。其工作原理如下:
@SpringBootApplication包含@EnableAutoConfiguration- Spring Boot 扫描所有 JAR 包中的
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件(Spring Boot 2.x 是 spring.factories) - 该文件列出了数百个自动配置类,如
WebMvcAutoConfiguration、DataSourceAutoConfiguration - 每个配置类上有
@ConditionalOnClass、@ConditionalOnMissingBean等条件注解 - 只有条件满足(如 classpath 中有某个类)时,对应的 Bean 才会被创建
mvn spring-boot:run --debug 或在启动参数中加 --debug 来查看哪些自动配置生效了、哪些被跳过了,非常有助于排查问题。
Spring Boot 启动流程
创建第一个 Spring Boot 应用
pom.xml 核心依赖
<!-- Spring Boot 父 POM,管理所有依赖版本 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>
<dependencies>
<!-- Web: 包含 Spring MVC + Tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 开发热重载 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- Lombok: 减少样板代码 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
主启动类
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication // 开启自动配置 + 组件扫描
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
第一个 REST Controller
package com.example.demo.controller;
import org.springframework.web.bind.annotation.*;
@RestController // = @Controller + @ResponseBody
@RequestMapping("/api/hello")
public class HelloController {
@GetMapping
public String hello() {
return "Hello, Spring Boot!";
}
@GetMapping("/{name}")
public String greet(@PathVariable String name) {
return "Hello, " + name + "!";
}
}
推荐项目分层结构
良好的项目结构是可维护性的基础。Spring Boot 项目推荐按职责分层,各层只依赖下层,不允许跨层调用。
application.yml 基础配置
spring:
application:
name: demo-service
datasource:
url: jdbc:postgresql://localhost:5432/demo
username: postgres
password: ${DB_PASSWORD} # 从环境变量读取
jpa:
hibernate:
ddl-auto: validate # 生产环境用 validate,不自动修改表结构
show-sql: false
server:
port: 8080
servlet:
context-path: /api
logging:
level:
com.example.demo: DEBUG
org.hibernate.SQL: DEBUG
${ENV_VAR} 语法)或 Spring Cloud Config / HashiCorp Vault 等配置中心管理。