spring-boot-dependency-injection

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Spring 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
    ,
    @Component
    , or
    @Repository
    classes.
  • 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定义。

Instructions

操作步骤

Follow these steps to implement proper dependency injection in Spring Boot:
按照以下步骤在Spring Boot中实现规范的依赖注入:

1. Identify Dependencies

1. 识别依赖

List all collaborators required by each class. Distinguish between mandatory dependencies (required for operation) and optional dependencies (feature-specific).
列出每个类所需的所有协作者。区分强制依赖(运行必需)和可选依赖(特定功能所需)。

2. Apply Constructor Injection

2. 应用构造器注入

Create constructors that accept all mandatory dependencies. Mark fields as final. Use Lombok @RequiredArgsConstructor to reduce boilerplate.
创建接收所有强制依赖的构造器。将字段标记为final。使用Lombok的@RequiredArgsConstructor减少样板代码。

3. Handle Optional Collaborators

3. 处理可选协作者

For optional dependencies, provide setter methods with @Autowired(required = false) or use ObjectProvider<T> for lazy resolution. Include default no-op implementations.
对于可选依赖,提供带有@Autowired(required = false)的setter方法,或使用ObjectProvider<T>实现延迟解析。包含默认的空操作实现。

4. Configure Beans

4. 配置Bean

Declare @Bean methods in @Configuration classes. Use conditional annotations (@ConditionalOnProperty, @ConditionalOnMissingBean) for environment-specific beans.
在@Configuration类中声明@Bean方法。使用条件注解(@ConditionalOnProperty、@ConditionalOnMissingBean)配置环境特定的Bean。

5. Resolve Ambiguity

5. 解决歧义

Apply @Primary to default implementations. Use @Qualifier with specific names when multiple beans of the same type exist.
为默认实现添加@Primary注解。当存在同一类型的多个Bean时,使用@Qualifier并指定具体名称。

6. Validate Wiring

6. 验证注入

Write unit tests that instantiate classes directly with mock dependencies. Add slice tests (@WebMvcTest, @DataJpaTest) to verify Spring context loads without errors.
编写直接实例化类并传入模拟依赖的单元测试。添加切片测试(@WebMvcTest、@DataJpaTest)以验证Spring上下文加载无错误。

7. Review Configuration

7. 审核配置

Ensure no field injection (@Autowired on fields) remains. Verify circular dependencies are resolved through domain events or extracted services.
确保不存在字段注入(字段上使用@Autowired)。通过领域事件或提取服务解决循环依赖问题。

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
    ./gradlew test
    or
    mvn test
    for validation.
  • Load supporting material from
    ./references/
    when deeper patterns or samples are required.
  • 项目需适配Java 17+和Spring Boot 3.5.x(或更高版本),以使用records和
    @ServiceConnection
  • 准备好构建工具以运行
    ./gradlew test
    mvn test
    进行验证。
  • 如需更深入的模式或示例,可从
    ./references/
    加载相关资料。

Workflow

工作流程

1. Map Collaborators

1. 映射协作者

  • Inventory constructors,
    @Autowired
    members, and configuration classes.
  • Classify dependencies as mandatory (must exist) or optional (feature-flagged, environment-specific).
  • 盘点构造器、
    @Autowired
    成员以及配置类。
  • 将依赖分类为强制依赖(必须存在)或可选依赖(功能标志控制、环境特定)。

2. Apply Constructor Injection

2. 应用构造器注入

  • Introduce constructors (or Lombok
    @RequiredArgsConstructor
    ) that accept every mandatory collaborator.
  • Mark injected fields
    final
    and protect invariants with
    Objects.requireNonNull
    if Lombok is not used.
  • Update
    @Configuration
    or
    @Bean
    factories to pass dependencies explicitly; consult
    ./references/reference.md
    for canonical bean wiring.
  • 添加接收所有强制协作者的构造器(或使用Lombok的
    @RequiredArgsConstructor
    )。
  • 将注入字段标记为
    final
    ,如果不使用Lombok,使用
    Objects.requireNonNull
    保护不变量。
  • 更新
    @Configuration
    @Bean
    工厂以显式传递依赖;可参考
    ./references/reference.md
    中的标准Bean注入方式。

3. Handle Optional Collaborators

3. 处理可选协作者

  • Supply setters annotated with
    @Autowired(required = false)
    or inject
    ObjectProvider<T>
    for lazy access.
  • Provide deterministic defaults (for example, no-op implementations) and document them inside configuration modules.
  • Follow
    ./references/examples.md#example-2-setter-injection-for-optional-dependencies
    for a full workflow.
  • 提供带有
    @Autowired(required = false)
    注解的setter方法,或注入
    ObjectProvider<T>
    实现延迟访问。
  • 提供确定性的默认实现(例如空操作实现),并在配置模块中记录。
  • 可参考
    ./references/examples.md#example-2-setter-injection-for-optional-dependencies
    获取完整流程。

4. Resolve Bean Selection

4. 解决Bean选择问题

  • Choose
    @Primary
    for dominant implementations and
    @Qualifier
    for niche variants.
  • Use profiles, conditional annotations, or factory methods to isolate environment-specific wiring.
  • Reference
    ./references/reference.md#conditional-bean-registration
    for conditional and profile-based samples.
  • 为主要实现选择
    @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
    ,
    @SpringBootTest
    ) only after constructor contracts are validated.
  • Reuse patterns in
    ./references/reference.md#testing-with-dependency-injection
    to select the proper test style.
  • 编写手动实例化类并传入模拟对象的单元测试,证明无需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:
    new UserService(mockRepo, mockEmailService);
    with no Spring context required.
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;
    }
}
  • 测试中可直接实例化:
    new UserService(mockRepo, mockEmailService);
    ,无需Spring上下文。

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
    CacheService.noOp()
    to ensure deterministic behavior when the optional bean is absent.
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;
    }
}
  • 提供
    CacheService.noOp()
    等回退实现,确保可选Bean不存在时行为确定。

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
    @Import
    , profiles, and conditional annotations to orchestrate cross-cutting modules.
Additional worked examples (including tests and configuration wiring) are available in
./references/examples.md
.
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();
    }
}
  • 结合
    @Import
    、配置文件和条件注解协调跨模块的配置。
更多完整示例(包括测试和配置注入)可在
./references/examples.md
中查看。

Best Practices

最佳实践

  • Prefer constructor injection for mandatory dependencies; allow Spring 4.3+ to infer
    @Autowired
    on single constructors.
  • Encapsulate optional behavior inside dedicated adapters or providers instead of accepting
    null
    pointers.
  • 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
  • 将可选行为封装在专用适配器或提供者中,而非接受空指针。
  • 保持服务构造器轻量化;当依赖数量超过四个时,提取协调器。
  • 领域层优先使用领域接口,将框架导入延迟到基础设施适配器中。
  • 在共享常量中记录Bean名称和限定符,避免因拼写错误导致的不匹配。

Constraints and Warnings

约束与警告

  • 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
    @Lazy
    usage to performance-sensitive paths and record the deferred initialization risk.
  • 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.
  • Never use
    @Autowired
    on fields when constructor injection is possible.
  • Be aware that optional dependencies can lead to
    NullPointerException
    if not properly handled.
  • Profile-specific beans can cause runtime errors if profiles are not correctly activated.
  • 避免字段注入和服务定位器模式,因为它们会隐藏依赖关系并阻碍单元测试。
  • 通过发布领域事件或提取共享抽象避免循环依赖。
  • 仅在性能敏感路径中使用
    @Lazy
    ,并记录延迟初始化的风险。
  • 添加特定配置文件的Bean时,必须添加激活该配置文件的匹配集成测试。
  • 确保每个可选协作者都有确定性的默认实现或功能标志处理路径。
  • 只要可以使用构造器注入,就不要在字段上使用
    @Autowired
  • 注意如果处理不当,可选依赖可能导致
    NullPointerException
  • 如果配置文件未正确激活,特定配置文件的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

相关技能

  • spring-boot-crud-patterns
    – service-layer orchestration patterns that rely on constructor injection.
  • spring-boot-rest-api-standards
    – controller-layer practices that assume explicit dependency wiring.
  • unit-test-service-layer
    – Mockito-based testing patterns for constructor-injected services.
  • spring-boot-crud-patterns
    – 依赖构造器注入的服务层协调模式。
  • spring-boot-rest-api-standards
    – 假设显式依赖注入的控制器层实践。
  • unit-test-service-layer
    – 针对构造器注入服务的Mockito测试模式。