【注解使用】使用@Autowired后提示:Field injection is not recommended(Spring团队不推荐使用Field注入)

 问题发生场景:

在使用 IDEA 开发 SpringBoot 项目时,在 Controller 类中使用注解 @Autowired 注入一个依赖出现了警告提示,查看其他使用该注解的地方同样出现了警告提示。这是怎么回事?由于先去使用了SpringBoot并没有对Spring进行系统性学习,所以做一个记录。

Field injection is not recommended(不再推荐使用字段注入) 

因为功力有限,所以以下内容均来自别人的博客:

Field injection is not recommended(Spring团队不推荐使用Field注入)_编程火箭车的博客-CSDN博客

为什么不推荐使用Field注入

  • 违反单一责任原则

添加新的依赖项非常容易。添加6个、10个甚至12个依赖项没有问题。当使用构造函数注入时,在某一点之后,构造函数参数的数量会变得过高,并且很明显会出现问题。依赖太多通常意味着类有太多的责任。这可能违反了单一职责原则和关注点分离,这表明类需要进一步的检查和重构。当直接注入字段时,没有这样的警告,因为这种方法可以无限扩展。

  • 依赖隐藏

使用依赖注入容器意味着类不再负责管理自己的依赖项。获取依赖项的职责是从类中提取的。由其他人现在负责提供依赖项——依赖注入容器或在测试中手动分配它们。当类不再负责获取其依赖项时,它应该使用公共接口(方法或构造函数)清楚地与它们通信。这样就可以清楚类需要什么,以及它是可选的(Setter)还是强制的(构造函数)。

  • 依赖注入容器耦合

DI 框架的核心思想之一是托管类不应该依赖于所使用的 DI 容器。换句话说,它应该只是一个普通的 POJO,可以独立地实例化它,前提是将所有必需的依赖项传递给它。通过这种方式,可以在单元测试中实例化它,而不需要启动 DI 容器,并单独测试它(使用的容器更像是集成测试)。如果没有容器耦合,则可以将该类作为托管或非托管类使用,甚至可以切换到新的 DI 框架。

然而,当直接注入字段时,无法直接用所有需要的依赖项实例化类。这意味着:

  • 有一种方法(通过调用默认构造函数)可以在一个状态中使用 new 关键字来创建一个对象,该状态中缺少一些强制协作者,使用将导致 NullPointerException。
  • 这样的类不能在 DI 容器(测试、其他模块)之外重用,因为除了反射之外,没有其他方法为它提供所需的依赖项。
  • 不变性

与构造函数不同,Field 注入不能用于将依赖项分配给最终字段。

那Spring团队推荐什么注入方式呢?

推荐构造器注入

官方文档里的说法:Core Technologies

Constructor-based or setter-based DI?

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. Note that use of the @Required annotation on a setter method can be used to make the property a required dependency.

The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.

Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.

Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI.

 最终要的是这句:

以下解释来自:https://www.cnblogs.com/joemsu/p/7688307.html#_caption_2

The Spring team generally advocates constructor injection as it enables one to implement application components as immutable objects and to ensure that required dependencies are not null. Furthermore constructor-injected components are always returned to client (calling) code in a fully initialized state.

​ 咳咳,再来简单的翻译一下:这个构造器注入的方式啊,能够保证注入的组件不可变,并且确保需要的依赖不为空。此外,构造器注入的依赖总是能够在返回客户端(组件)代码的时候保证完全初始化的状态
 

下面来简单的解释一下:

  • 依赖不可变:其实说的就是final关键字
  • 依赖不为空(省去了我们对其检查):当要实例化FooController的时候,由于自己实现了有参数的构造函数,所以不会调用默认构造函数,那么就需要Spring容器传入所需要的参数,所以就两种情况:1、有该类型的参数->传入,OK 。2:无该类型的参数->报错。所以保证不会为空,Spring总不至于传一个null进去吧 😦
  • 完全初始化的状态:这个可以跟上面的依赖不为空结合起来,向构造器传参之前,要确保注入的内容不为空,那么肯定要调用依赖组件的构造方法完成实例化。而在Java类加载实例化的过程中,构造方法是最后一步(之前如果有父类先初始化父类,然后自己的成员变量,最后才是构造方法,这里不详细展开。)。所以返回来的都是初始化之后的状态。

结论


应尽量避免 Field 注入。推荐使用构造函数或方法来注入依赖项。两者各有利弊,其用法取决于具体情况。但是,由于这些方法可以混合使用,所以这不是非必须选择一种,可以将 Setter 和构造函数注入合并到一个类中。构造函数更适合于强制依赖项和以不变性为目标的情况。对于可选的依赖项,Setter 更好。

然后我在另一篇博客中也读到,使用@Resource替代@Autowired就没有这个提示了.....

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/38266.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分布式 - 消息队列Kafka:Kafka消费者和消费者组

文章目录 1. Kafka 消费者是什么?2. Kafka 消费者组的概念?3. Kafka 消费者和消费者组有什么关系?4. Kafka 多个消费者如何同时消费一个分区? 1. Kafka 消费者是什么? 消费者负责订阅Kafka中的主题,并且从…

【数据结构OJ题】反转链表

原题链接:https://leetcode.cn/problems/reverse-linked-list/description/ 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 方法一:三指针翻转法 使用三个结构体指针n1,n2,n3,原地修改结点…

VSCode如何设置高亮

一、概述 本文主要介绍在 VSCode 看代码时,怎样使某个单词高亮显示,主要通过以下三步实现: 安装 highlight-words 插件 配置 highlight-words 插件 设置高亮快捷键F8 工作是嵌入式开发的,代码主要是C/C的,之前一直用…

【Linux】高级IO

目录 IO的基本概念 钓鱼五人组 五种IO模型 高级IO重要概念 同步通信 VS 异步通信 阻塞 VS 非阻塞 其他高级IO 阻塞IO 非阻塞IO IO的基本概念 什么是IO? I/O(input/output)也就是输入和输出,在著名的冯诺依曼体系结构当中…

ROS学习笔记(三)---好用的终端Terminator

ROS学习笔记文章目录 01. ROS学习笔记(一)—Linux安装VScode 02. ROS学习笔记(二)—使用 VScode 开发 ROS 的Python程序(简例) 一、Terminator是什么? 在前面的学习中,为了运行hello.py我是在vscode频繁的点击运行窗口的“”号…

智谷星图赵俊:让人才和区块链产业“双向奔赴”丨对话MVP

区块链产业需要什么样的人才?赵俊很有发言权。 赵俊是北京智谷星图科技有限公司的技术总监,也是FISCO BCOS官方认证讲师。他2017年接触区块链,随后选择人才培育领域深耕。“为区块链行业引进更多人才这件事很有价值,跟我的职业理…

菜单和内容滚动的联动原理及代码

之前写代码有个需求:左侧是一个菜单,右边是内容,点击左侧菜单右边内容滚动到对应位置,右边内容滚动到某位置时,左侧菜单也会选中对应的菜单项。UI如下:这是大多网站的移动端都会有的需求。 解决方案一&…

高忆管理:什么是一码通?有什么好处?

在经过券商开户后,除了其间的财物账户、沪深股账户外,还有一个一码通账户,什么是一码通?它有什么好处?关于这些,高忆管理为大家预备了以下参阅内容。 什么是一码通? 一码通账户,一般…

【C语言】小游戏-扫雷(清屏+递归展开+标记)

大家好&#xff0c;我是深鱼~ 目录 一、游戏介绍 二、文件分装 三、代码实现步骤 1.制作简易游戏菜单 2. 初始化棋盘(11*11) 3.打印棋盘(9*9) 4.布置雷 5.计算(x,y)周围8个坐标的和 6.排查雷 <1>清屏后打印棋盘 <2>递归展开 <3>标记雷 四、完整代…

视频监控有哪些存储方式?安防监控应该如何选择存储模式?

视频监控系统涉及到大量的视频数据&#xff0c;需要对这些数据进行存储&#xff0c;以备日后查看或备份。视频监控的存储需求需要根据场所的实际情况进行选择&#xff0c;以保证监控数据的有效存储和日后的调阅、回溯。 当前视频监控的存储方式&#xff0c;通常有以下几种&…

Golang协程,通道详解

进程、线程以及并行、并发 关于进程和线程 进程&#xff08;Process&#xff09;就是程序在操作系统中的一次执行过程&#xff0c;是系统进行资源分配和调度的基 本单位&#xff0c;进程是一个动态概念&#xff0c;是程序在执行过程中分配和管理资源的基本单位&#xff0c;每…

【BASH】回顾与知识点梳理(二十三)

【BASH】回顾与知识点梳理 二十三 二十三. Linux 账号管理&#xff08;二&#xff09;23.1 账号管理新增与移除使用者&#xff1a; useradd, 相关配置文件, passwd, usermod, userdelusermoduserdel 23.2 用户功能&#xff08;普通用户可使用&#xff09;idfingerchfnchsh 23.3…

【数据库系统】--【2】DBMS架构

DBMS架构 01DBMS架构概述02 DBMS的物理架构03 DBMS的运行和数据架构DBMS的运行架构DBMS的数据架构PostgreSQL的体系结构RMDB的运行架构 04DBMS的逻辑和开发架构DBMS的层次结构DBMS的开发架构DBMS的代码架构 05小结 01DBMS架构概述 02 DBMS的物理架构 数据库系统的体系结构 数据…

腾讯Perfdog支持Windows PC端体验性能测试

一、背景 最近在做抖音的小玩法&#xff0c;其基于unity引擎&#xff0c;然后挂载到直播伴侣。以及Perfdog近期也支持了Windows的测试&#xff0c;所以做一个体验测试。 二、如何做 查看PC端的支持&#xff0c;目前是beat版本 选择或搜索自己需要的对应的程序&#xff0c;如…

大数据Flink(五十九):Flink on Yarn的三种部署方式介绍以及注意

文章目录 Flink on Yarn的三种部署方式介绍以及注意 一、Pre-Job 模式部署作业

对任意类型数都可以排序的函数:qsort函数

之前我们学习过冒泡排序&#xff1a; int main() {int arr[] { 9,7,8,6,5,4,3,2,1,0 };int sz sizeof(arr)/sizeof(arr[0]);int i 0;for (i 0; i < sz-1; i) {int j 0;for (j 0; j < sz-1-i; j) {if (arr[j] > arr[j 1]){int temp 0;temp arr[j];arr[j] ar…

接口测试及接口抓包常用的测试工具

接口 接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互逻辑依赖关系等。 接口测试的重要性 是节省时间前后端不…

七、dokcer-compose部署springboot的jar

1、准备 打包后包名为 ruoyi-admin.jar 增加接口 httpL//{ip}:{port}/common/test/han #环境变量预application.yml 中REDIS_HOSTt的值&#xff0c;去环境变量去找&#xff1b;如果找不到REDIS_HOST就用myredis 1、Dockerfile FROM hlw/java:8-jreRUN ln -sf /usr/share/z…

私密相册管家-加密码保护私人相册照片安全

App Store史上最安全、最强大、最卓越的私密相册App&#xff01;再也不用担心私密照片视频被别人看见了&#xff01;
私密相册为你提供多重密码保护机制、简单便捷的照片存储空间&#xff0c;完美地将你的私密照片远离一切恶意偷窥者的窥探&#xff01; 【产品功能】
 √ 支…

Redis—持久化

这里写目录标题 AOF三种写回策略写回策略的优缺点AOF 重写机制AOF后台重写AOF优缺点使用命令 RDBRDB 持久化的工作原理执行快照时&#xff0c;数据能被修改吗RDB 持久化的优点RDB 持久化的缺点 混合持久化大key对持久化的影响 AOF 保存写操作命令到日志的持久化方式&#xff0…