我就是奇迹

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Spring 依赖注入(Dependency Injection, DI)

在 Spring 依赖注入(Dependency Injection, DI) 中,有三种主要的方式:

1. 构造函数注入(Constructor Injection)

2. Setter 方法注入(Setter Injection)

3. 字段注入(Field Injection)

 

1. 构造函数注入(Constructor Injection) ✅ 推荐方式

 

原理:通过构造函数为 Bean 传递依赖,在对象创建时就完成依赖注入。

优点

不可变性:依赖是 final 的,保证依赖不会被修改,符合 SOLID 原则(SRP, DI)。

强制依赖注入:创建对象时就提供了所有必要的依赖,避免了空指针问题。

更方便单元测试:可以通过构造函数直接提供 mock 依赖。

 

示例

@Component
public class UserService {
    private final UserRepository userRepository;

    @Autowired  // Spring 4.3+ 可省略
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void registerUser(String name) {
        userRepository.save(name);
    }
}
最佳实践:推荐使用构造函数注入,并且让依赖 final,确保不可变。

 


 

2. Setter 方法注入(Setter Injection)

 

原理:Spring 在创建对象后,通过Setter 方法注入依赖。

优点

适用于可选依赖(非必须的依赖)。

可以在运行时动态修改依赖。

 

缺点

依赖可能是 null,导致 NullPointerException

破坏不可变性(对象在创建后依然可以被修改)。

依赖不明确,可能创建出**半初始化(partially initialized)**对象。

 

示例

@Component
public class UserService {
    private UserRepository userRepository;

    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}
适用场景:如果某些依赖是可选的,可以使用 Setter 注入,但构造函数注入仍是更好的选择。

 


 

3. 字段注入(Field Injection) ❌ 不推荐

 

原理:Spring 直接在字段上使用 @Autowired,无需构造函数或 Setter 方法。

优点

代码更简洁,省去了构造函数和 Setter 方法。

 

缺点

破坏封装性,外部无法控制依赖,难以进行单元测试(无法直接 mock 依赖)。

依赖是隐藏的,违反 DI 原则,可维护性变差。

不能使用 final 关键字,导致对象可以被随意修改。

 

示例

@Component
public class UserService {
    @Autowired
    private UserRepository userRepository;
}
避免使用:字段注入适合临时/实验代码,但在生产环境推荐构造函数注入。

 


 

三者对比总结

方式

是否推荐

优点

缺点

适用场景

构造函数注入

✅ 强烈推荐

依赖不可变、强制依赖注入、利于测试

代码略长

推荐默认使用

Setter 方法注入

⚠️ 次选

适用于可选依赖

破坏不可变性、可能为空

依赖可选或需要修改时

字段注入

❌ 不推荐

代码最简洁

破坏封装、难以测试、依赖隐藏

临时测试或实验代码

最佳实践

默认使用 构造函数注入,并让依赖 final(保证不可变)。

Setter 注入仅适用于可选依赖,如日志、配置等。

避免使用字段注入,特别是测试驱动开发(TDD)时。

 

如果你的代码需要可测试性、可维护性和更好的设计,构造函数注入是最佳选择! 🚀

posted on 2025-04-01 12:12  我就是奇迹  阅读(240)  评论(0)    收藏  举报