IDEA使用@Autowired注解为什么会提示不建议?
在使用IDEA编写Spring相关的项目时,当在字段上使用@Autowired注解时,总会出现一个波浪线提示:”Field injection is not recommended.” 这让我不禁疑惑:我每天都在使用这种方式,为何不被推荐呢?今天,我决定深入探究其中的原因。
众所周知,Spring框架提供了三种可选的依赖注入方式:构造器注入、Setter方法注入和Field注入。在此,我们将详细探讨这三种注入方式的使用场景。
构造器注入
如下所示,在使用构造器注入时,我们可以将属性字段设置为final。通过构造器注入,当对AService进行实例化时,BService对象必须提前初始化完成,从而确保被注入的对象一定不为null。构造器注入适用于对象之间存在强依赖关系的场景,但无法解决循环依赖问题(因为必须互相依赖对方初始化完成,从而产生冲突,无法解决)。
关于循环依赖问题,推荐阅读Spring循环依赖是什么及其解决方式 。该文章会更深入地讲解Spring中循环依赖的原理和解决方法。
@Service
public class AService {
private final BService bService;
@Autowired //spring framework 4.3之后可以不用在构造方法上标注@Autowired
public AService(BService bService) {
this.bService = bService;
}
}
Setter 方法注入
使用Setter方法进行注入时,Spring会在执行默认的无参构造函数实例化Bean对象后,调用Setter方法来注入依赖。这种方式下,我们可以将”required”属性设置为false,表示如果注入的Bean对象不存在,Spring会直接跳过注入,而不会报错。
@Service
public class AService {
private BService bService;
@Autowired(required = false)
public void setbService(BService bService) {
this.bService = bService;
}
}
Field注入
的确,Field注入在视觉上非常简洁美观,因此被广泛采用。使用Field注入时,Spring容器会在对象实例化完成之后,通过反射机制来设置需要注入的字段。
@Service
public class AService {
@Autowired
private BService bService;
}
为什么IDEA不推荐使用Field注入
经查阅多方资料,我找到了以下几个重要原因,导致Field注入可能不太被推荐使用:
- 可能导致空指针异常:如果对象创建不使用Spring容器,而是直接使用无参构造方法new一个对象,此时使用注入的对象可能导致空指针异常。
- 不能使用final修饰字段:缺乏final修饰会使得类的依赖可变,进而可能引发一些不可预料的异常。通常情况下,可以使用构造方法注入来声明强制依赖的Bean,使用Setter方法注入来声明可选依赖的Bean。
- 可能更容易违反单一职责原则:这是一个关键原因。使用字段注入可能会轻易地在类中引入各种依赖,导致类的职责过多,但开发者往往难以察觉。相比之下,使用构造方法注入,当构造方法的参数过多时,会提示开发者重构这个类。
- 不利于写单元测试:在单元测试中,使用Field注入,必须使用反射的方式来Mock依赖对象。
为了解决这些问题,我们可以采用以下替代方案:
- 当类有强依赖于其他Bean时,优先使用构造方法注入。
- 对于可选依赖,可以使用Setter方法注入,并在代码中处理可能出现的引用对象不存在的情况。
Spring官方的态度
Spring官方文档在依赖注入这一节中的确没有明确讨论字段注入这种方式,而更加强调了构造方法注入和Setter方法注入。构造方法注入被视为首选的依赖注入方式,因为它可以确保依赖的对象在创建时就被注入,从而避免了一些潜在的问题,比如空指针异常和类的可变性。
Setter方法注入在可选依赖的场景下也很有用,但需要开发者自行处理依赖对象不存在的情况。
总的来说,Spring团队强烈推荐使用构造方法注入,因为它在很多方面都更加安全和可靠。同时,选择适当的依赖注入方式也可以根据具体情况灵活使用。
总结
在Spring中使用依赖注入时,首选构造方法注入。虽然构造方法注入无法解决循环依赖问题,但当循环依赖出现时,我们应该优先考虑是否代码结构设计存在问题。当然,也不排除某些必须使用循环依赖的场景,此时字段注入可能会派上用场。
最后,我想强调的是,在平时使用IDEA的过程中,关注代码下划线或飘黄的提醒是很重要的。这些提示可以帮助我们学习他人总结的最佳实践经验,提升自己的代码水平。
本文首发:https://www.panziye.com/java/7639.html
感谢支持!
IDEA使用@Autowired注解为什么会提示不建议?的更多相关文章
- Spring5:@Autowired注解、@Resource注解和@Service注解
什么是注解 传统的Spring做法是使用.xml文件来对bean进行注入或者是配置aop.事物,这么做有两个缺点: 1.如果所有的内容都配置在.xml文件中,那么.xml文件将会十分庞大:如果按需求分 ...
- @Autowired注解与@Qualifier注解搭配使用
问题:当一个接口实现由两个实现类时,只使用@Autowired注解,会报错,如下图所示 实现类1 实现类2 controller中注入 然后启动服务报错,如下所示: Exception encount ...
- @Resource与@Autowired注解的区别
一.写本博文的原因 年初刚加入到现在的项目时,在使用注解时我用的@Resource.后来,同事:你怎么使用@Resource注解?我:使用它有错吗?同事:没错,但是现在都使用@Autowired.我: ...
- @Autowired注解和启动自动扫描的三种方式(spring bean配置自动扫描功能的三种方式)
前言: @Autowired注解代码定义 @Target({ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, Elemen ...
- @Autowired注解与@Qualifier注解搭配使用----解决多实现选择注入问题
问题:当一个接口实现由两个实现类时,只使用@Autowired注解,会报错,如下图所示 实现类1 实现类2 controller中注入 然后启动服务报错,如下所示: Exception encount ...
- @Resource与@Autowired注解的区别踩坑者入
一.写本博文的原因 有些童鞋搞不为什么要用@Resource或者@Autowired,咱们一起研究下 @Resource默认按照名称方式进行bean匹配,@Autowired默认按照类型方式进行bea ...
- @Autowired注解的使用
使用Spring时,通过Spring注入的Bean一般都被定义成private,并且要有getter和setter方法,显得比较繁琐,增加了代码量,而且有时会搞忘造成错误. 可以使用@Autowire ...
- Spring中@Autowired注解、@Resource注解的区别
Spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource.@PostConstruct以及@PreDestroy. @Resour ...
- 转:Spring中@Autowired注解、@Resource注解的区别
Pay attention: When using these annotations, the object itself has to be created by Spring context. ...
- Spring中@Autowired注解与自动装配
1 使用配置文件的方法来完成自动装配我们编写spring 框架的代码时候.一直遵循是这样一个规则:所有在spring中注入的bean 都建议定义成私有的域变量.并且要配套写上 get 和 set方法. ...
随机推荐
- 2022-07-21:给定一个字符串str,和一个正数k, 你可以随意的划分str成多个子串, 目的是找到在某一种划分方案中,有尽可能多的回文子串,长度>=k,并且没有重合。 返回有几个回文子串。 来
2022-07-21:给定一个字符串str,和一个正数k, 你可以随意的划分str成多个子串, 目的是找到在某一种划分方案中,有尽可能多的回文子串,长度>=k,并且没有重合. 返回有几个回文子串 ...
- 2020-11-30:java中,卡表和记忆集的区别?
福哥答案2020-12-04:[答案来自此链接:](http://bbs.xiangxueketang.cn/question/530)这两个都是G1收集器中的概念记忆集,RemeberSet,用来记 ...
- golang基础面试题,不完整
启动流程 Q.go的init函数是什么时候执行的? Q.多个init函数执行顺序能保证吗? Q.go init 的执行顺序,注意是不按导入规则的(这里是编译时按文件名的顺序执行的) Q.init函数能 ...
- Rust如何引入源码作为依赖
问题描述 通常我们在rust项目中引入第三方依赖包时,会直接指定包的版本,这种方式指定后,Cargo在编译时会从crates.io这个源中下载这些依赖包. [package] name = " ...
- weex create test-app Error: Cannot find module '../package.json'
weex create 报错 D:\YLKJPro>weex create test-app Error: Cannot find module '../package.json' at Fun ...
- VuePress2.0构建项目文档系统
VuePress2.0构建项目文档系统 参考TerraMours 官网.https://terramours.site/ 文件结构参考: 1.修改首页README.md 修改项目下的README.md ...
- Python的Lambda函数: 一把极简编程的瑞士军刀
Python中的lambda函数,或者叫匿名函数,是一个极其强大的工具.它以简洁.优雅的语法提供了创建函数的快速方式.在本篇文章中,我们将全方位地深入研究lambda函数的用法和特点,通过理论和实例相 ...
- .Net全网最简RabbitMQ操作【强烈推荐】
[前言] 本文自1年前的1.0版本推出以来,已被业界大量科技公司采用.同时也得到了.Net圈内多位大佬的关注+推荐,文章也被多家顶级.Net/C#公众号转载. 现在更新到了7.0版本,更好的服务各位. ...
- 2023安洵杯web两道WP
Web CarelessPy 在首页提示存在eval和login的路由,在download存在任意文件下载 访问eval可以读取目录下的文件,知道/app/pycache/part.cpython-3 ...
- 自然语言处理 Paddle NLP - 情感分析技术及应用SKEP-实践
Part A. 情感分析任务 众所周知,人类自然语言中包含了丰富的情感色彩:表达人的情绪(如悲伤.快乐).表达人的心情(如倦怠.忧郁).表达人的喜好(如喜欢.讨厌).表达人的个性特征和表达人的立场等等 ...