java:依赖注入的三种注入方式:字段注入、构造器注入、settler方法注入

1. 字段注入 (Field Injection) - 最常见但不推荐

当你将 @Autowired 注解直接标注在字段(成员变量) 上时,Spring会通过反射机制直接设置该字段的值,即使它是 private 的。

@Service
public class UserService {

    @Autowired // 字段注入
    private UserRepository userRepository;

    // ...
}
  • 方式:字段注入

  • 特点:代码非常简洁,但也是最不推荐的方式(原因见后文)。


2. Setter 方法注入 (Setter Injection)

当你将 @Autowired 注解标注在对应的 Setter方法 上时,Spring会在构造完对象后,调用这个Setter方法来注入依赖。

@Service
public class UserService {

    private UserRepository userRepository;

    @Autowired // Setter方法注入
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}
  • 方式:Setter注入

  • 特点:比字段注入更灵活,允许在对象创建后重新配置依赖(但通常不需要这么做)。


3. 构造函数注入 (Constructor Injection) - 官方推荐的最佳实践

当你将 @Autowired 注解标注在类的构造函数上时,Spring会通过调用这个构造函数来创建对象,并将所需的依赖作为参数传入。

注意:在Spring 4.3及以后的版本中,如果一个类只有一个构造函数,那么 @Autowired 注解可以省略,Spring会自动使用该构造函数进行注入。

@Service
public class UserService {

    private final UserRepository userRepository;

    // @Autowired 注解在只有一个构造函数时可省略
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}
  • 方式:构造函数注入

  • 特点:这是目前最推荐的方式。


总结与对比

注入方式代码示例优点缺点
字段注入@Autowired private Foo foo;代码极其简洁1. 不易测试(必须通过反射或启动容器来注入)
2. 无法声明为 final(破坏了不可变性)
3. 容易导致空指针(如果容器配置错误,字段为 null
4. 破坏封装性(通过反射强制给私有字段赋值)
Setter注入@Autowired public void setFoo(Foo f)灵活性高,允许可选依赖或重新注入对象可能在Set之前被使用,导致状态不完整
构造函数注入@Autowired public ClassA(Foo f)1. 强依赖性:保证对象在构造完成后就处于完全初始化的状态
2. 不可变:依赖可声明为 final
3. 易于测试:不依赖容器,可直接通过 new 传入Mock对象进行测试
4. 代码安全:避免空指针问题
依赖过多时,构造函数参数列表会很长

最佳实践

强烈推荐优先使用构造函数注入。 这是Spring官方自4.x版本以来倡导的方式,理由如下:

  1. 不可变性final 字段保证了依赖在对象生命周期内不会被意外更改。

  2. 完全初始化的状态:对象一旦被创建,其所有必需依赖都已就绪,避免了部分初始化的不一致状态。

  3. 更好的可测试性:你可以毫不费力地编写单元测试,只需简单地调用构造函数并传入模拟依赖。

  4. 代码更清晰:构造函数明确地声明了创建一个该类的实例所必须的依赖项。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值