spring-boot-3

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

When to Use

适用场景

Load this skill when:
  • Building a Spring Boot 3.3+ service or API
  • Wiring beans with dependency injection
  • Defining configuration properties and validation
  • Implementing REST controllers and service layers
在以下场景下使用本技能:
  • 构建Spring Boot 3.3+服务或API
  • 通过依赖注入(DI)装配Bean
  • 定义配置属性并进行验证
  • 实现REST控制器与服务层

Critical Patterns

核心设计模式

Pattern 1: Constructor injection only

模式1:仅使用构造函数注入

Always use constructor injection; avoid field injection.
始终使用构造函数注入;避免字段注入。

Pattern 2: Typed configuration properties

模式2:类型化配置属性

Use @ConfigurationProperties with validation, not scattered @Value.
结合验证使用@ConfigurationProperties,而非分散的@Value注解。

Pattern 3: Transaction boundaries at service layer

模式3:服务层事务边界

Apply @Transactional on application services, not controllers.
在应用服务上添加@Transactional注解,而非控制器。

Code Examples

代码示例

Example 1: Configuration properties with validation

示例1:带验证的配置属性

java
package com.acme.config;

import jakarta.validation.constraints.NotBlank;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@Validated
@ConfigurationProperties(prefix = "payment")
public record PaymentProperties(
  @NotBlank String provider,
  @NotBlank String apiKey
) { }
java
package com.acme;

import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@ConfigurationPropertiesScan
public class Application { }
java
package com.acme.config;

import jakarta.validation.constraints.NotBlank;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.validation.annotation.Validated;

@Validated
@ConfigurationProperties(prefix = "payment")
public record PaymentProperties(
  @NotBlank String provider,
  @NotBlank String apiKey
) { }
java
package com.acme;

import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@ConfigurationPropertiesScan
public class Application { }

Example 2: Service with constructor injection + transaction

示例2:构造函数注入+事务的服务

java
package com.acme.order.application;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public final class OrderService {
  private final OrderRepository repository;

  public OrderService(OrderRepository repository) {
    this.repository = repository;
  }

  @Transactional
  public void placeOrder(OrderCommand command) {
    repository.save(command.toEntity());
  }
}
java
package com.acme.order.application;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public final class OrderService {
  private final OrderRepository repository;

  public OrderService(OrderRepository repository) {
    this.repository = repository;
  }

  @Transactional
  public void placeOrder(OrderCommand command) {
    repository.save(command.toEntity());
  }
}

Example 3: REST controller with DTO records

示例3:使用DTO记录的REST控制器

java
package com.acme.order.api;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/orders")
public final class OrderController {
  private final OrderService service;

  public OrderController(OrderService service) {
    this.service = service;
  }

  @PostMapping
  public ResponseEntity<OrderResponse> place(@RequestBody OrderRequest request) {
    service.placeOrder(request.toCommand());
    return ResponseEntity.ok(new OrderResponse("ok"));
  }

  public record OrderRequest(String sku, int qty) {
    public OrderCommand toCommand() { return new OrderCommand(sku, qty); }
  }

  public record OrderResponse(String status) { }
}
java
package com.acme.order.api;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/orders")
public final class OrderController {
  private final OrderService service;

  public OrderController(OrderService service) {
    this.service = service;
  }

  @PostMapping
  public ResponseEntity<OrderResponse> place(@RequestBody OrderRequest request) {
    service.placeOrder(request.toCommand());
    return ResponseEntity.ok(new OrderResponse("ok"));
  }

  public record OrderRequest(String sku, int qty) {
    public OrderCommand toCommand() { return new OrderCommand(sku, qty); }
  }

  public record OrderResponse(String status) { }
}

Anti-Patterns

反模式

Don't: Use field injection

禁止:使用字段注入

java
// BAD: field injection
@Service
public class OrderService {
  @org.springframework.beans.factory.annotation.Autowired
  private OrderRepository repository;
}
java
// BAD: field injection
@Service
public class OrderService {
  @org.springframework.beans.factory.annotation.Autowired
  private OrderRepository repository;
}

Don't: Scatter configuration with @Value

禁止:使用@Value分散配置

java
// BAD: hard to validate and test
@Service
public class PaymentService {
  @org.springframework.beans.factory.annotation.Value("${payment.apiKey}")
  private String apiKey;
}
java
// BAD: hard to validate and test
@Service
public class PaymentService {
  @org.springframework.beans.factory.annotation.Value("${payment.apiKey}")
  private String apiKey;
}

Quick Reference

快速参考

TaskPattern
Inject dependenciesConstructor injection only
Read config@ConfigurationProperties + @Validated
Transactions@Transactional on services
任务模式
注入依赖仅使用构造函数注入
读取配置@ConfigurationProperties + @Validated
事务管理在服务层添加@Transactional

Resources

参考资源