https://my.oschina.net/u/5079097/blog/5289666
 

引言

使用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不胜感激 !

[转帖]Spring为啥不推荐使用@Autowired注解?的更多相关文章

  1. spring + myBatis 常见错误:@Autowired注解失败

    今天配置spring+myBatis的时候,使用注解@Autowired把持久层dao注入service层的时候总是报错. 查了好久才发现,居然是配置文件路径写错了.basepackge的路径一定要正 ...

  2. Spring学习(9)--- @Autowired注解(二)

    可以使用@Autowired注解那些众所周知的解析依赖性接口,比如:BeanFactory,ApplicationContext,Environment,ResourceLoader,Applicat ...

  3. Spring学习(8)--- @Autowired注解(一)

    可以将@Autowired注解为“传统”的setter方法 package com.mypackage; import org.springframework.beans.factory.annota ...

  4. @Autowired注解的使用

    使用Spring时,通过Spring注入的Bean一般都被定义成private,并且要有getter和setter方法,显得比较繁琐,增加了代码量,而且有时会搞忘造成错误. 可以使用@Autowire ...

  5. Spring官方都推荐使用的@Transactional事务,为啥我不建议使用!

    GitHub 17k Star 的Java工程师成神之路,不来了解一下吗! GitHub 17k Star 的Java工程师成神之路,真的不来了解一下吗! GitHub 17k Star 的Java工 ...

  6. Spring中@Autowired注解、@Resource注解的区别

    Spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource.@PostConstruct以及@PreDestroy. @Resour ...

  7. 转:Spring中@Autowired注解、@Resource注解的区别

    Pay attention: When using these annotations, the object itself has to be created by Spring context. ...

  8. Spring中 @Autowired注解与@Resource注解的区别

    Spring中 @Autowired注解与@Resource注解的区别在Spring 3.X中经常使用到@Autowired和@Resource进行装配.这两个注解的差异在何处???相同点:@Reso ...

  9. Spring中@Autowired注解与自动装配

    1 使用配置文件的方法来完成自动装配我们编写spring 框架的代码时候.一直遵循是这样一个规则:所有在spring中注入的bean 都建议定义成私有的域变量.并且要配套写上 get 和 set方法. ...

  10. Spring学习(12)--- @Autowired与@Resource 对比

    Spring不但支持自己定义的@Autowired注解,还支持由JSR-250规范定义的几个注解,如:@Resource. @PostConstruct及@PreDestroy. 1. @Autowi ...

随机推荐

  1. X410的白嫖方案

    微软商店下的x410要收费试用也就几天,记录白嫖方案.配置和使用跳转到上一篇文章:Windows下使用图形化的Havoc C2 编译运行 GitHub上start最多的是这个仓库,但是已经很久没有维护 ...

  2. Python——第二章:列表的概念

    在编程中,列表(List)是一种常用的数据结构,用于存储一组有序的元素.列表是Python中的内置数据类型之一,它允许你在一个变量中存储多个值,并且这些值可以是不同的数据类型,包括整数.浮点数.字符串 ...

  3. Python——第一章:占位——pass

    pass: 常用于代码占位 a = 10 if a > 100: pass 当设计代码时,有些条件或代码还没有想好要如何处理,先用pass做占位,后续可以回来继续写.如果不写pass则会报错,因 ...

  4. Python——第一章:循环语句while

    循环语句可以让我们的代码重复的去执行 while循环: while 条件:        代码 过程: 判断while循环的条件是否为真, 如果真, 执行代码. 然后再次判断条件.....直到条件为假 ...

  5. 快速掌握服务网格系列二:云原生、K8S、服务网格(Service Mesh)及微服务之间的关系

    快速掌握服务网格系列二:云原生.K8S.服务网格(Service Mesh)及微服务之间的关系 首先看下CNCF对云原生的定义: Cloud native technologies empower o ...

  6. 理论+实践详解最热的LLM应用框架LangChain

    本文分享自华为云社区<LangChain是什么?LangChain的详细介绍和使用场景>,作者:码上开花_Lancer . 一.概念介绍 1.1 Langchain 是什么? 官方定义是: ...

  7. 人人都在聊的云原生数据库Serverless到底是什么?

    摘要:华为云数据库营销专家Tony Chen和华为云数据库高级产品经理佳恩开展了一场关于云原生数据库与Serverless结合的直播对话. 云计算的迅猛发展推动了数据库的变革,云原生数据库成为当前数据 ...

  8. 华为云FusionInsight助力宇宙行打造金融数据湖新标杆

    摘要:工行采用了华为云FusionInsight MRS大数据存算分离方案,实现了大数据平台与OBS对象存储服务的对接,将原有的HDFS数据无缝迁移到OBS上.在保证性能的前提下,实现了计算与存储独立 ...

  9. 打破“双十定律”,华为云AI推动超级抗菌药Drug X研发加速

    摘要:学科交叉已经逐渐变成了科技创新的一个主要源泉,成为这个科学时代一个不可替代的研究范式.在科技与技术合力赋能之下,中国科研人创新奋斗再出新成果,人类与病菌的博弈因此有了新武器. 本文分享自华为云社 ...

  10. 云图说|图解DGC:基于华为智能数据湖解决方案的一体化数据治理平台

    摘要:数据湖治理中心DGC,帮助企业快速构建从数据集成到数据服务的端到端智能数据系统,消除数据孤岛,统一数据标准,加快数据变现,实现数字化转型. 本文分享自华为云社区<[云图说]第232期 图解 ...