Spring Boot Best Practices
Priority: P0
Implementation Guidelines
Dependency Injection (DI)
- Constructor Injection: ALWAYS use Constructor Injection for immutability. Use
@RequiredArgsConstructor(Lombok) to reduce boilerplate. Mark all dependencies asfinal. - Avoid @Autowired: NEVER use field injection. It prevents unit testing without Spring context and hides dependencies.
Configuration & Data
- Type-Safe Config: Use
@ConfigurationPropertieswith Records (Java 17+) instead of@Value. Use Spring profile-specific files (e.g.,application-dev.yml,application-prod.yml) and set active profile viaSPRING_PROFILES_ACTIVE. Never hardcode secret values in properties files. - Validation: Combine with
@Validatedand Jakarta Bean Validation (@NotNull,@NotEmpty) to fail fast at startup. Useapplication.yamlfor structured configuration. - DTOs: Use
recordsas immutable DTOs to reduce boilerplate and ensure thread safety. Handle empty values withOptionalto avoidNullPointerException.
Observability & Quality
- Error Handling: Implement
@ControllerAdviceandProblemDetails(RFC 7807) for standardized error responses. - Logging: Use
SLF4Jwith@Slf4j. Implement Structured Logging by logging arguments (log.info("id: {}", id)). - Tooling: Mandate
SpotlessorCheckstylefor code formatting. Usesdkmanto manage JDK 21+ versions.
Anti-Patterns
- No @Autowired on fields: Use constructor injection via @RequiredArgsConstructor.
- No Setters on dependencies: Declare all injected fields as final.
- No context.getBean(): Inject dependencies via constructor DI.
- No log-and-swallow: Rethrow or handle exceptions explicitly.