spring-boot-dependency-injection
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSpring Boot Dependency Injection
Spring Boot 依赖注入
This skill captures the dependency injection approach promoted in this repository: constructor-first design, explicit optional collaborators, and deterministic configuration that keeps services testable and framework-agnostic.
本技能涵盖了本仓库所推崇的依赖注入方法:构造函数优先设计、显式声明可选协作者,以及确保服务可测试且与框架无关的确定性配置。
Overview
概述
- Prioritize constructor injection to keep dependencies explicit, immutable, and mockable.
- Treat optional collaborators through guarded setters or providers while documenting defaults.
- Resolve bean ambiguity intentionally through qualifiers, primary beans, and profiles.
- Validate wiring with focused unit tests before relying on Spring's TestContext framework.
- 优先使用构造函数注入,确保依赖关系清晰、不可变且可模拟。
- 通过受保护的setter方法或提供者来处理可选协作者,同时记录默认行为。
- 通过限定符、主Bean和配置文件来主动解决Bean歧义问题。
- 在依赖Spring的TestContext框架之前,先通过针对性的单元测试验证依赖装配。
When to Use
适用场景
- Implement constructor injection for new ,
@Service, or@Componentclasses.@Repository - Replace legacy field injection while modernizing Spring modules.
- Configure optional or pluggable collaborators (feature flags, multi-tenant adapters).
- Audit bean definitions before adding integration tests or migrating Spring Boot versions.
- 为新的、
@Service或@Component类实现构造函数注入。@Repository - 在现代化Spring模块时,替换传统的字段注入方式。
- 配置可选或可插拔的协作者(如功能标志、多租户适配器)。
- 在添加集成测试或迁移Spring Boot版本之前,审核Bean定义。
Prerequisites
前置条件
- Align project with Java 17+ and Spring Boot 3.5.x (or later) to leverage records and .
@ServiceConnection - Keep build tooling ready to run or
./gradlew testfor validation.mvn test - Load supporting material from when deeper patterns or samples are required.
./references/
- 项目需适配Java 17+及Spring Boot 3.5.x(或更高版本),以使用records和特性。
@ServiceConnection - 准备好构建工具,以便运行或
./gradlew test进行验证。mvn test - 当需要深入了解模式或示例时,从加载相关参考资料。
./references/
Workflow
工作流
1. Map Collaborators
1. 梳理协作者
- Inventory constructors, members, and configuration classes.
@Autowired - Classify dependencies as mandatory (must exist) or optional (feature-flagged, environment-specific).
- 盘点构造函数、成员及配置类。
@Autowired - 将依赖分为必填项(必须存在)和可选项(功能标志控制、特定环境)。
2. Apply Constructor Injection
2. 应用构造函数注入
- Introduce constructors (or Lombok ) that accept every mandatory collaborator.
@RequiredArgsConstructor - Mark injected fields and protect invariants with
finalif Lombok is not used.Objects.requireNonNull - Update or
@Configurationfactories to pass dependencies explicitly; consult@Beanfor canonical bean wiring../references/reference.md
- 添加接收所有必填协作者的构造函数(或使用Lombok的)。
@RequiredArgsConstructor - 如果不使用Lombok,将注入字段标记为,并使用
final确保不变性。Objects.requireNonNull - 更新或
@Configuration工厂类,显式传递依赖;如需标准Bean装配方式,请参考@Bean。./references/reference.md
3. Handle Optional Collaborators
3. 处理可选协作者
- Supply setters annotated with or inject
@Autowired(required = false)for lazy access.ObjectProvider<T> - Provide deterministic defaults (for example, no-op implementations) and document them inside configuration modules.
- Follow for a full workflow.
./references/examples.md#example-2-setter-injection-for-optional-dependencies
- 提供标注有的setter方法,或注入
@Autowired(required = false)以实现延迟访问。ObjectProvider<T> - 提供确定性的默认实现(比如空操作实现),并在配置模块中记录这些默认行为。
- 完整工作流可参考。
./references/examples.md#example-2-setter-injection-for-optional-dependencies
4. Resolve Bean Selection
4. 解决Bean选择歧义
- Choose for dominant implementations and
@Primaryfor niche variants.@Qualifier - Use profiles, conditional annotations, or factory methods to isolate environment-specific wiring.
- Reference for conditional and profile-based samples.
./references/reference.md#conditional-bean-registration
- 为主要实现类使用,为特定变体使用
@Primary。@Qualifier - 使用配置文件、条件注解或工厂方法来隔离特定环境的依赖装配。
- 条件装配和基于配置文件的示例可参考。
./references/reference.md#conditional-bean-registration
5. Validate Wiring
5. 验证依赖装配
- Write unit tests that instantiate classes manually with mocks to prove Spring-free testability.
- Add slice or integration tests (,
@WebMvcTest,@DataJpaTest) only after constructor contracts are validated.@SpringBootTest - Reuse patterns in to select the proper test style.
./references/reference.md#testing-with-dependency-injection
- 编写单元测试,手动使用模拟对象实例化类,证明无需Spring即可测试。
- 仅在构造函数契约验证通过后,再添加切片测试或集成测试(、
@WebMvcTest、@DataJpaTest)。@SpringBootTest - 可复用中的模式来选择合适的测试方式。
./references/reference.md#testing-with-dependency-injection
Examples
示例
Basic Constructor Injection
基础构造函数注入
java
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final EmailService emailService;
public User register(UserRegistrationRequest request) {
User user = User.create(request.email(), request.name());
userRepository.save(user);
emailService.sendWelcome(user);
return user;
}
}- Instantiate directly in tests: with no Spring context required.
new UserService(mockRepo, mockEmailService);
java
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final EmailService emailService;
public User register(UserRegistrationRequest request) {
User user = User.create(request.email(), request.name());
userRepository.save(user);
emailService.sendWelcome(user);
return user;
}
}- 可在测试中直接实例化:,无需Spring上下文。
new UserService(mockRepo, mockEmailService);
Intermediate: Optional Dependency with Guarded Setter
进阶:带保护Setter的可选依赖
java
@Service
public class ReportService {
private final ReportRepository reportRepository;
private CacheService cacheService = CacheService.noOp();
public ReportService(ReportRepository reportRepository) {
this.reportRepository = reportRepository;
}
@Autowired(required = false)
public void setCacheService(CacheService cacheService) {
this.cacheService = cacheService;
}
}- Provide fallbacks such as to ensure deterministic behavior when the optional bean is absent.
CacheService.noOp()
java
@Service
public class ReportService {
private final ReportRepository reportRepository;
private CacheService cacheService = CacheService.noOp();
public ReportService(ReportRepository reportRepository) {
this.reportRepository = reportRepository;
}
@Autowired(required = false)
public void setCacheService(CacheService cacheService) {
this.cacheService = cacheService;
}
}- 提供这类回退实现,确保当可选Bean不存在时行为是确定的。
CacheService.noOp()
Advanced: Conditional Configuration Across Modules
高级:跨模块条件配置
java
@Configuration
@Import(DatabaseConfig.class)
public class MessagingConfig {
@Bean
@ConditionalOnProperty(name = "feature.notifications.enabled", havingValue = "true")
public NotificationService emailNotificationService(JavaMailSender sender) {
return new EmailNotificationService(sender);
}
@Bean
@ConditionalOnMissingBean(NotificationService.class)
public NotificationService noopNotificationService() {
return NotificationService.noOp();
}
}- Combine , profiles, and conditional annotations to orchestrate cross-cutting modules.
@Import
Additional worked examples (including tests and configuration wiring) are available in .
./references/examples.mdjava
@Configuration
@Import(DatabaseConfig.class)
public class MessagingConfig {
@Bean
@ConditionalOnProperty(name = "feature.notifications.enabled", havingValue = "true")
public NotificationService emailNotificationService(JavaMailSender sender) {
return new EmailNotificationService(sender);
}
@Bean
@ConditionalOnMissingBean(NotificationService.class)
public NotificationService noopNotificationService() {
return NotificationService.noOp();
}
}- 结合、配置文件和条件注解来协调跨模块的配置。
@Import
更多完整示例(包括测试和配置装配)可查看。
./references/examples.mdBest Practices
最佳实践
- Prefer constructor injection for mandatory dependencies; allow Spring 4.3+ to infer on single constructors.
@Autowired - Encapsulate optional behavior inside dedicated adapters or providers instead of accepting pointers.
null - Keep service constructors lightweight; extract orchestrators when dependency counts exceed four.
- Favor domain interfaces in the domain layer and defer framework imports to infrastructure adapters.
- Document bean names and qualifiers in shared constants to avoid typo-driven mismatches.
- 必填依赖优先使用构造函数注入;Spring 4.3+版本可自动推断单个构造函数的注解。
@Autowired - 将可选行为封装在专用适配器或提供者中,而非接受指针。
null - 保持服务构造函数简洁;当依赖数量超过四个时,提取协调器。
- 领域层优先使用领域接口,将框架导入延迟到基础设施适配器中。
- 将Bean名称和限定符记录在共享常量中,避免因拼写错误导致的不匹配。
Constraints
约束条件
- Avoid field injection and service locator patterns because they obscure dependencies and impede unit testing.
- Prevent circular dependencies by publishing domain events or extracting shared abstractions.
- Limit usage to performance-sensitive paths and record the deferred initialization risk.
@Lazy - Do not add profile-specific beans without matching integration tests that activate the profile.
- Ensure each optional collaborator has a deterministic default or feature-flag handling path.
- 避免使用字段注入和服务定位器模式,因为它们会模糊依赖关系并阻碍单元测试。
- 通过发布领域事件或提取共享抽象来避免循环依赖。
- 仅在性能敏感路径中使用,并记录延迟初始化的风险。
@Lazy - 不要添加特定配置文件的Bean,除非有对应的激活该配置文件的集成测试。
- 确保每个可选协作者都有确定性的默认实现或功能标志处理路径。
Reference Materials
参考资料
- extended documentation covering annotations, bean scopes, testing, and anti-pattern mitigations
- progressive examples from constructor injection basics to multi-module configurations
- curated excerpts from the official Spring Framework documentation (constructor vs setter guidance, conditional wiring)
- 涵盖注解、Bean作用域、测试及反模式缓解的扩展文档
- 从构造函数注入基础到多模块配置的进阶示例
- 官方Spring Framework文档精选片段(构造函数与setter注入指南、条件装配)
Related Skills
相关技能
- – service-layer orchestration patterns that rely on constructor injection.
spring-boot-crud-patterns - – controller-layer practices that assume explicit dependency wiring.
spring-boot-rest-api-standards - – Mockito-based testing patterns for constructor-injected services.
unit-test-service-layer
- —— 依赖构造函数注入的服务层编排模式。
spring-boot-crud-patterns - —— 基于显式依赖装配的控制器层实践。
spring-boot-rest-api-standards - —— 针对构造函数注入服务的Mockito测试模式。
unit-test-service-layer