围绕“Jev、Java 与 Spring”展开的讨论,核心价值不只是认识某个工具或人物,而是重新观察 Java 语言、JVM 生态与 Spring 框架之间如何协作。由于来源摘要没有提供具体对话内容,下面不推断节目中的观点,而是沿着标题涉及的 Java 和 Spring,给出一套可以直接实践的工程方法。
Java 负责表达,Spring 负责装配
在现代 Spring 应用中,两者的职责边界越来越清晰:
- Java 提供类型系统、记录类、异常处理、并发模型和模块化能力。
- Spring 管理对象生命周期、依赖注入、Web 请求、配置、数据访问与可观测性。
- 构建工具负责解析依赖、运行测试并生成可部署产物。
这意味着应用代码不必处处依赖框架。业务规则可以写成普通 Java 类,只有 HTTP、数据库或消息系统等边界需要接入 Spring。这样的结构更容易测试,也能降低升级框架时的改造成本。
例如,一个价格计算器没有必要继承任何 Spring 类型:
package com.example.demo.pricing;
import java.math.BigDecimal;
public final class PriceCalculator {
public BigDecimal applyDiscount(BigDecimal price, int percent) {
if (price.signum() < 0) {
throw new IllegalArgumentException("price must not be negative");
}
if (percent < 0 || percent > 100) {
throw new IllegalArgumentException("percent must be between 0 and 100");
}
return price.multiply(BigDecimal.valueOf(100L - percent))
.divide(BigDecimal.valueOf(100));
}
}
Spring 只需要在系统边界调用它,而不是侵入它的每一行逻辑。
搭建一个最小可运行的 Spring Boot 服务
可以用 Java 21 和 Spring Boot 3.x 建立一个小型 HTTP 服务。运行前请确认 java -version 显示 JDK 21,并把下面文件放进对应目录。
项目结构如下:
demo/
├── pom.xml
└── src/main/java/com/example/demo/
├── DemoApplication.java
└── GreetingController.java
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<properties>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
应用入口:
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);
}
}
HTTP 控制器使用 Java record 表达不可变响应:
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class GreetingController {
@GetMapping("/greetings")
public Greeting greet(
@RequestParam(defaultValue = "developer") String name) {
return new Greeting("Hello, " + name + "!", Runtime.version().feature());
}
public record Greeting(String message, int javaVersion) {}
}
启动并调用接口:
cd demo
mvn spring-boot:run
打开另一个终端:
curl 'http://localhost:8080/greetings?name=Spring'
预期会得到类似结果:
{"message":"Hello, Spring!","javaVersion":21}
这个例子刻意保持简单,但它展示了一个重要方向:使用 Java 自身的语言能力定义数据和规则,让 Spring 专注于 HTTP 映射、序列化与应用启动。
不要让“能启动”代替工程验证
Spring Boot 的自动配置提高了开发速度,也可能掩盖隐式行为。团队至少应该检查以下几项:
- JDK 与 Spring Boot 的兼容范围:升级 JDK 前查看当前 Spring Boot 版本的支持矩阵,不要只依据本地编译是否成功。
- 依赖由 BOM 统一管理:尽量不要给 Spring 管理的常用依赖单独指定版本,否则容易形成不兼容组合。
- 边界输入必须校验:HTTP 参数、JSON 请求体和配置值都来自系统外部,不能假设它们始终正确。
- 启动测试不能缺席:至少保留一个能够加载 Spring 上下文的测试,尽早发现 Bean 冲突和配置错误。
- 生产配置不得写死:数据库密码、令牌和证书应通过环境变量或密钥管理系统注入。
可以加入一个最小启动测试:
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
}
}
运行全部验证:
mvn clean verify
采用时应关注什么
Java 与 Spring 的组合并不要求所有代码都“Spring 化”。更稳妥的做法是:领域模型使用普通 Java,外部适配器使用 Spring,依赖版本交给 Spring Boot 管理,并通过测试保护升级路径。
准备把这种方式引入现有项目时,可以按下面的清单推进:
- 明确生产环境的 JDK 基线,并在 CI 中使用同一主版本。
- 盘点手工声明版本的依赖,确认是否可以交回 Spring Boot 管理。
- 优先使用构造器注入,避免隐藏依赖关系。
- 把核心规则从 Controller、Repository 和配置类中拆出来。
- 每次升级先阅读迁移说明,再运行单元测试、上下文测试和接口测试。
- 对启动时间、内存和吞吐量进行实际测量,不根据框架印象做结论。
框架负责减少重复劳动,Java 负责提供稳定的语言基础,而工程团队仍然要对边界、版本和运行结果负责。这三者的关系理顺之后,Spring 项目才能在快速开发之外保持可维护性。