Spring为啥不推荐使用@Autowired注解?

引言
使用IDEA开发时,同组小伙伴都喜欢用@Autowired注入,代码一片warning,看着很不舒服,@Autowired作为Spring的亲儿子,为啥在IDEA中提示了一个警告:Field injection is not recommended

在这里插入图片描述

想搞清楚这个问题之前,首先先了解一下依赖注入的几种方式

Spring的三种注入方式
属性(filed)注入
这种注入方式就是在bean的变量上使用注解进行依赖注入。本质上是通过反射的方式直接注入到field。这是我平常开发中看的最多也是最熟悉的一种方式。

@Autowired 
UserDao userDao;
复制代码

构造器注入
将各个必需的依赖全部放在带有注解构造方法的参数中,并在构造方法中完成对应变量的初始化,这种方式,就是基于构造方法的注入。比如:

final
UserDao userDao;

@Autowired
public UserServiceImpl(UserDao userDao) {
    this.userDao = userDao;
}
复制代码

set方法注入
通过对应变量的setXXX()方法以及在方法上面使用注解,来完成依赖注入。比如:

private UserDao userDao;

@Autowired
public void setUserDao (UserDao userDao) {
    this.userDao = userDao;
}
复制代码

属性注入可能出现的问题
问题一
基于 field 的注入可能会带来一些隐含的问题。来我们举个例子:

@Autowired
private User user;

private String company;

public UserDaoImpl(){
    this.company = user.getCompany();
}
复制代码

编译过程不会报错,但是运行之后报NullPointerException

Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate […]: Constructor threw exception; nested exception is java.lang.NullPointerException
复制代码
Java 在初始化一个类时,是按照静态变量或静态语句块 –> 实例变量或初始化语句块 –> 构造方法 -> @Autowired 的顺序。所以在执行这个类的构造方法时,user对象尚未被注入,它的值还是 null。

问题二
不能有效的指明依赖。相信很多人都遇见过一个bug,依赖注入的对象为null,在启动依赖容器时遇到这个问题都是配置的依赖注入少了一个注解什么的。这种方式就过于依赖注入容器了,当没有启动整个依赖容器时,这个类就不能运转,在反射时无法提供这个类需要的依赖。

问题三
依赖注入的核心思想之一就是被容器管理的类不应该依赖被容器管理的依赖,换成白话来说就是如果这个类使用了依赖注入的类,那么这个类摆脱了这几个依赖必须也能正常运行。然而使用变量注入的方式是不能保证这点的。

spring建议
Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies.

翻译过来就是:

强制依赖就用构造器方式
可选、可变的依赖就用setter注入

使用@Resource代替@Autowired
@Resource有2个属性name和type。在spring中name属性定义为bean的名字,type这是bean的类型。如果属性上加@Resource注解那么他的注入流程是

如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常。
如果指定了name,则从上下文中查找名称匹配的bean进行装配,找不到则抛出异常。
如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或是找到多个,都会抛出异常。
如果既没有指定name,又没有指定type,则默认按照byName方式进行装配;如果没有匹配,按照byType进行装配。
@Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖@Qualifier或@Primary注解一起来修饰。

使用@RequiredArgsConstructor构造器方式注入
这种形式就是Spring推荐使用的构造器方式注入,此种方式是lombok包下的注解,如果使用此种方式,需要项目中引入lombok,例如:

@RequiredArgsConstructor
public class UserDaoImpl{
	private final User user;
}
复制代码

最后
如果你觉得此文对你有一丁点帮助,点个赞。或者可以加入我的开发交流群:1025263163相互学习,我们会有专业的技术答疑解惑

如果你觉得这篇文章对你有点用的话,麻烦请给我们的开源项目点点star:http://github.crmeb.net/u/defu不胜感激 !

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
### 回答1: 对于Spring来说,虽然Autowired功能非常强大,但是使用不当也会带来一些问题。例如,自动装配的过程中可能出现多个Bean都可以进行装配的情况,而Spring并不知道应该选择哪一个Bean进行注入。这种歧义性可能会导致程序无法启动。另外,使用@Autowired注解还可能降低代码的可读性和可维护性,因为很难直观地看出哪些Bean被注入到了某个类中。因此,Spring 5.1版本开始,官方推荐使用构造器注入或者是Setter注入来完成Bean的注入工作,以解决使用@Autowired注解带来的问题。 ### 回答2: Spring不建议使用@Autowired是因为它存在一些潜在的问题和风险。 首先,@Autowired注解是基于Java反射机制实现的,它会在运行时通过反射来设置依赖的对象。这样的处理方式会导致一定的性能损耗,尤其在注入的依赖非常多时,会影响系统的性能。 其次,@Autowired注解在注入依赖时是按照类型进行匹配的,如果存在多个可选的依赖对象,Spring会自动选择其中一个进行注入。这种方式可能会引发歧义性问题,导致注入的对象与预期的不一致。 另外,通过@Autowired注解,可能会引发循环依赖的问题。当两个或多个Bean之间存在循环依赖关系时,Spring容器可能无法正确解决依赖关系,导致应用程序无法启动。 为了解决以上问题,Spring在5.x版本中推荐使用构造函数注入(Constructor Injection)或Setter方法注入(Setter Injection)。这两种方式可以显式地表达出要注入的依赖,提高了代码的可读性和可维护性。 使用构造函数注入时,我们可以在Bean的构造函数中显式地声明需要注入的依赖,并且通过构造函数的参数列表将依赖传递进来。这样做可以确保依赖的完整性和正确性。 使用Setter方法注入时,我们可以在Bean中定义一个Setter方法,并在方法中通过传入参数的方式将依赖对象注入到Bean中。这种方式可以减少构造函数的参数数量,提高代码的可读性。 综上所述,尽管@Autowired注解仍然可以使用,但Spring推荐使用构造函数注入或Setter方法注入来替代@Autowired注解,以提高系统的性能和可维护性。 ### 回答3: Spring并不是不建议使用@Autowired注解,而是推荐使用更为明确的注解,比如@Qualifier或者@Resource。 @Autowired注解Spring中常用的依赖注入注解,它可以自动装配需要的依赖,但在使用时存在一定的模糊性。当一个类中存在多个相同类型的依赖时,Spring无法确定具体要注入哪一个,从而引发歧义性。为了解决这个问题,Spring提供了更为明确的注解进行依赖注入。 @Qualifier注解可以与@Autowired配合使用,用于指定具体要注入的依赖对象的名称。通过在@Autowired后添加@Qualifier注解,可以指定具体的bean名称,确保注入的对象是我们期望的类型。 @Resource注解是JSR-250(Java Specification Requests)规范中的一部分,由JDK提供。与@Autowired类似,@Resource也可以实现依赖注入,但相较于@Autowired,@Resource更加明确和精确。@Resource注解可以根据bean的名称或者类型进行注入,从而避免了模糊性。 虽然@Autowired注解仍然可以使用,但为了避免歧义和提高代码的清晰度,Spring推荐使用@Qualifier或者@Resource注解来注入依赖,以确保注入的对象符合预期。这样可以提高代码的可读性,减少因为依赖注入引发的问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CRMEB定制开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值