【Spring】为什么Spring官方不推荐使用@Autowired属性注入

Spring的依赖注入

让我们来看看Spring的几个依赖注入方法:构造函数注入、Setter注入和属性注入。

1.构造函数注入

在初始化对象时,通过构造函数参数将依赖对象注入依赖项。
Spring推荐的注入方法。

private DependencyA dependencyA;
private DependencyB dependencyB;;

//@Autowired不是必需的,Spring 4添加了一个新特性。如果类只提供了带参数的构造函数,你不需要为它的内部属性写@Autowired注释,Spring会自动为你注入属性。
@Autowired
public DI(DependencyA dependencyA, DependencyB dependencyB) {
    this.dependencyA = dependencyA;
    this.dependencyB = dependencyB;
}
  • 优点:你可以在对象初始化后得到一个可用的对象,并且单元测试可以实例化,而无需使用Mock启动DI容器。

  • 缺点:当要注入的对象很多时,构造函数参数列表会很长,不够灵活。如果有多个注入方法,并且每个方法只需要注入几个指定的依赖项,则需要提供多个重载构造函数。

2.Setter注入

IoC服务提供者通过调用成员变量提供的setter函数将依赖对象注入依赖类。
如果存在可选的可变依赖项,则使用Setter注入,可选依赖项可以通过@Autowired指定(required = false)。构造函数注入不能做到这一点,因为它应用于所有构造函数。

private DependencyA dependencyA;
private DependencyB dependencyB;

@Autowired
public void setDependencyA(DependencyA dependencyA) {
    this.dependencyA = dependencyA;
}

@Autowired(required = false)
public void setDependencyB(DependencyB dependencyB) {
    this.dependencyB = dependencyB;
}

Setter注入更加灵活,可以选择性地注入所需的对象。

3.属性注入

属性注入使用bean变量上的注释进行依赖项注入,本质上是通过反射直接注入到字段中,这应该是开发中最常见的方法之一。

@Autowired
private DependencyA dependencyA;

@Autowired
private DependencyB dependencyB;

属性注入的限制和替代方案

限制

  • 以前的属性注入应该是我们最常用的依赖注入方法,直接引入bean然后对变量使用@Autowired就行了,但是后来你会发现在IDEA中会给出一个警告“不推荐Field注入”。

  • 因为Field注入很容易使用,所以我们有意无意地引入了很多依赖项,当注入太多依赖项时,意味着类承担了太多的责任,这违反了面向对象的单一责任原则,而且无论引入多少都没有警告,因为这种方法可以无限扩展。

  • 然而,属性注入也有限制,不能在声明为final/immutable的字段上使用@Autowired注释,因为这些字段必须在类实例化时初始化。

  • 而且,属性注入对单元测试不友好,你必须使用Spring的IoC容器来创建这些bean(和IoC容器强耦合),但是单元测试原则上要快,启动IoC容器太慢,如果是构造注入,我们完全可以把bean当成普通的类来创建对象,只需直接通过构造传递即可。

替代方案

如果我们不使用@Autowired,我们也可以使用JDK提供的@Resource注释,它减少了与Spring的耦合,而且同样易于使用,所以它同样容易被滥用。

  • 更推荐的方法是使用构造注入。当需要更多依赖项时,构造函数参数看起来就越丑,我们可以使用Lombok简化构造函数注入。

Lombok提供了三个相关的注释来简化依赖注入。
@AllArgsConstructor用于生成包含所有字段构造的构造函数方法。
@NoArgsConstructor用于生成不带参数的构造函数方法。
@RequiredArgsConstructor生成只包含声明为final或非空字段的构造函数方法。

//使用Lombok注解 @RequiredArgsConstructor + final,自动生成带final的参数构造方法
@RequiredArgsConstructor
public class DI{
    private final  DependencyA dependencyA ;
}

参考

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值