--- id: backend.java-spring.awareness title: Java / Spring Boot(了解级):读懂项目结构、IoC 与依赖注入、分层、事务注解和与 Go / Python 的对照 type: lesson domain: backend stack: [java-spring] tags: [Java, Spring Boot, IoC, 依赖注入, 注解, 事务, JPA, MyBatis, 虚拟线程] level: basic prerequisites: [backend.go.index] est_hours: 2 related: [backend.java-spring.scenario.call-java-service, backend.java-spring.interview] week: [14] order: 1 --- # Java / Spring Boot(了解级):读懂项目结构、IoC 与依赖注入、分层、事务注解和与 Go / Python 的对照 > 定位:**能读懂、能对接、面试能聊概念**,不作为主线。BOSS直聘 2026-10-23 的调研中,有 AI 应用岗位写了“熟悉 Java / Go / Python 其中之一”,或者团队已有 Java 业务系统需要 Agent 去调用。示例只用 JDK,在 JDK 26(JDK 21+ 即可)上实际运行通过;Spring 代码为示意,未编译。以官方文档为准:https://docs.spring.io/spring-boot/ 。 ## 解释说明 ### 与你熟悉的技术对照 | 概念 | Java / Spring Boot | Go | Python / FastAPI | | --- | --- | --- | --- | | 数据类 | `record` | struct | `dataclass` / Pydantic 模型 | | 路由 | `@RestController` + `@GetMapping` | Gin 路由 | `@app.get` | | 依赖注入 | IoC 容器 + 构造器注入 | 手动在 main 中组装 | `Depends` | | 参数校验 | `@Valid` + Bean Validation | binding 标签 | Pydantic | | 数据访问 | Spring Data JPA / MyBatis | database/sql、sqlc、GORM | SQLAlchemy | | 事务 | `@Transactional` | 手动 `tx.Begin/Commit` | `session.begin()` | | 并发 | 线程池、虚拟线程(JDK 21) | goroutine | asyncio | | 构建 | Maven / Gradle | go build | uv / pip | ### Spring 的核心概念 - **IoC 容器**:对象(Bean)由容器创建和管理,你声明依赖,容器注入。推荐**构造器注入**(依赖不可变、便于测试)。 - **分层**:Controller(接收请求)→ Service(业务逻辑、事务)→ Repository(数据访问)。 - **自动配置**:Spring Boot 根据依赖和配置自动创建常用组件(数据源、Web 服务器),配置在 `application.yml`。 - **`@Transactional` 的坑**:基于代理实现,同一个类内部方法调用不经过代理,事务不生效;默认只对运行时异常回滚。 - **AI 相关**:Spring AI、LangChain4j 等框架让 Java 项目也能接入大模型(版本变化快,以官方文档为准)。 ### 怎么快速读懂一个 Spring Boot 项目 1. 看 `pom.xml` / `build.gradle`:依赖了什么。 2. 找带 `@SpringBootApplication` 的启动类。 3. 看 `application.yml`:数据库、端口、外部服务地址。 4. 从 Controller 顺着调用链读到 Service 和 Repository。 5. 看全局异常处理(`@RestControllerAdvice`)和拦截器 / 过滤器(鉴权)。 ## 案例 你负责的 Python Agent 需要调用公司的 Java 订单服务:读懂它的接口定义(Controller 和 DTO)、错误码、鉴权方式、分页规则,把它封装成 Agent 的工具。 ## 代码示例 只用 JDK 的对照示例 [examples/java-basics/OrderDemo.java](examples/java-basics/OrderDemo.java)(`java OrderDemo.java` 运行通过):record、接口 + 构造器注入、Optional、Stream 分组汇总、BigDecimal 金额、虚拟线程。 ```text 跨租户查询被拒绝: 订单不存在: B001 t1 按状态汇总: {paid=20.00, refunded=5.00} 用 double 计算金额的问题: 0.1 + 0.2 = 0.30000000000000004 1000 个虚拟线程计数结果: 1000 ``` 对应的 Spring Boot 写法(示意,未编译): ```java @RestController @RequestMapping("/orders") class OrderController { private final OrderService service; OrderController(OrderService service) { this.service = service; } // 构造器注入,无需 @Autowired @GetMapping("/{id}") OrderDto get(@PathVariable String id, @RequestHeader("X-Tenant-Id") String tenant) { return OrderDto.from(service.get(tenant, id)); } } @Service class OrderService { private final OrderRepository repo; OrderService(OrderRepository repo) { this.repo = repo; } @Transactional public void refund(String tenant, String id) { /* 修改订单 + 写退款记录,在一个事务中 */ } } @RestControllerAdvice class GlobalErrors { @ExceptionHandler(NotFoundException.class) ResponseEntity> notFound(NotFoundException e) { return ResponseEntity.status(404).body(Map.of("code", "NOT_FOUND", "message", e.getMessage())); } } ``` ## 易错点 - 金额用 `double`。 - 同类内部调用带 `@Transactional` 的方法,以为事务生效。 - 受检异常被捕获后吞掉,事务没有回滚。 - 在面试中把“了解”说成“精通”:如实说明能读懂并对接,主语言是 Go / Python。 ## 面试常问 - 什么是 IoC 和依赖注入? - `@Transactional` 什么情况下会失效? - 你不会 Java,如何和 Java 团队协作?