【注解使用】使用@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.rhkb.cn/news/91195.html

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

相关文章

三、性能测试场景设计

性能测试场景设计 一、引言:如果公司要求你去做性能测试,遇到这些场景,我们要如何设计?二、6种常见设计方法1、普通性能场景设计2、负载测试性能场景3、压力测试场景4、面向目标性能场景 一、引言:如果公司要求你去做性…

W6100-EVB-PICO 做UDP Server进行数据回环测试(七)

前言 前面我们用W6100-EVB-PICO 开发板在TCP Client和TCP Server模式下,分别进行数据回环测试,本章我们将用开发板在UDP Server模式下进行数据回环测试。 UDP是什么?什么是UDP Server?能干什么? UDP (User Dataqram P…

海量数据迁移,亚马逊云科技云数据库服务为大库治理提供新思路

1.背景 目前,文档型数据库由于灵活的schema和接近关系型数据库的访问特点,被广泛应用,尤其是游戏、互联网金融等行业的客户使用MongoDB构建了大量应用程序,比如游戏客户用来处理玩家的属性信息;又如股票APP用来存储与时…

Jmeter常用功能-参数化介绍

JMeter也有像LR中的参数化,本篇就来介绍下JMeter的参数化如何去实现。 参数化:录制脚本中有登录操作,需要输入用户名和密码,假如系统不允许相同的用户名和密码同时登录,或者想更好的模拟多个用户来登录系统。 这个时…

RabbitMQ简单使用

RabbitMq是一个消息中间件:它接收消息、转发消息。你可以把它理解为一个邮局:当你向邮箱里寄出一封信后,邮递员们就能最终将信送到收信人手中。 RabbitMq、消息相关术语如下: 生产者:生产者只发送消息,发…

React(5)

1.受控组件案例 1.1之前的影院案例改写 import React, { Component } from react import axios from axios import BetterScroll from better-scroll import ./css/02_tab.cssexport default class Cinema extends Component {constructor() {super();this.state {cinemaLis…

Jmeter进阶使用:BeanShell实现接口前置和后置操作

一、背景 我们使用Jmeter做压力测试或者接口测试时,除了最简单的直接对接口发起请求,很多时候需要对接口进行一些前置操作:比如提前生成测试数据,以及一些后置操作:比如提取接口响应内容中的某个字段的值。举个最常用…

只需要自动售货机,商业模式立马大变样!

随着互联网、大数据和人工智能的蓬勃发展,商业模式正以前所未有的方式融合,其中自动售货机作为新零售模式的一颗璀璨明珠,正引领着购物体验的革命。这个巧妙的结合将消费者的便利、数据的智能分析以及科技的创新融为一体,重新定义…

Mysql:Access denied for user ‘root‘@‘localhost‘ (using password:YES)解决方案

最近在配置Maven以及Mybatis时,连接localhost数据库时出现无法连接,用cmd测试时报错:Access denied for user ‘ODBC’‘localhost’ (using password: NO),这个意思就是不允许远程访问,一开始笔者进入mysql试了一下是…

Untiy Json和Xml的序列化和反序列化

Json的序列化和反序列化 1.定义数据类 [Serializable] public class ZoomPoint {// 点名称, 将作为Key被字典存储public string name;// 轴心X坐标public Vector2 pivot Vector2.one / 2;// 放大倍率,小于1是为缩小倍率,小于0是取绝对值,不…

机器学习中基本的数据结构说明

数据维度或数据结构 当我们在机器学习或深度学习的领域内处理数据,我们通常会遇到四种主要的数据结构:标量,向量,矩阵和张量。理解这些基本数据结构是非常重要的,因为它们是机器学习算法和神经网络的核心。下面是对这…

NLPR、SenseTime 和 NTU 加速自动视频纵向编辑

视频人像编辑技术已经在电视、视频和电影制作中得到了应用,并有望在不断发展的网真场景中发挥关键作用。最先进的方法已经可以逼真地将同源音频合成为视频。现在,来自北京模式识别国家实验室(NLPR)、商汤科技研究和南洋理工大学的…

go.sum are different when using go mod vendor/download

本地Golang配置 今天本地编译一个项目,遇到以下错误 PS D:\Code\Golang\jiankunking\k8s-ext> go mod tidy go: downloading github.com/huaweicloud/huaweicloud-sdk-go-obs v3.23.4incompatible verifying github.com/gin-gonic/ginv1.7.3: checksum mismat…

JVM 内存结构快速入门

文章目录 一、简介二、JVM内存区域2.1 方法区2.3.2 永久代和元空间 2.2 堆2.1.2 对象的创建和销毁 2.2 栈内存2.2.1 栈帧的组成和作用2.2.2 栈的特点 2.4 程序计数器2.4.1 程序计数器的作用和使用场景 一、简介 Java 内存模型(Java Memory Model,JMM&…

微信小程序云开发快速入门(2/4)

前言 我们对《微信小程序云开发快速入门(1/4)》的知识进行回顾一下。在上章节我们知道了云开发的优势以及能力,并且我们还完成了码仔备忘录的本地版到网络版的改造,主要学习了云数据库同时还通过在小程序使用云API直接操作了云数…

做海外游戏推广有哪些条件?

做海外游戏推广需要充分准备和一系列条件的支持。以下是一些关键条件: 市场调研和策略制定:了解目标市场的文化、玩家偏好、竞争格局等是必要的。根据调研结果制定适合的推广策略。 本地化:将游戏内容、界面、语言、货币等进行本地化&#…

智慧工地源码,PC+APP源码,项目管理端+企业监管端+数据大屏端

智慧工地概念 智慧工地是一种崭新的工程全生命周期管理理念,是指运用信息化手段,通过对工程项目进行精确设计和施工模拟,围绕施工过程管理,建立互联协同、智能生产、科学管理的施工项目信息化生态圈,并将此数据在虚拟…

DIP:《Deep Image Prior》经典文献阅读总结与实现

文章目录 Deep Image Prior1. 方法原理1.1 研究动机1.2 方法 2. 实验验证2.1 去噪2.2 超分辨率2.3 图像修复2.4 消融实验 3. 总结 Deep Image Prior 1. 方法原理 1.1 研究动机 动机 深度神经网络在图像复原和生成领域有非常好的表现一般归功于神经网络学习到了图像的先验信息…

解压版 MySQL 数据库的安装与配置

目录 1 下载2 安装3 配置3.1 添加环境变量3.2 新建配置文件3.3 初始化MySQL3.4 注册MySQL服务3.5 启动MySQL服务3.6 修改默认账户密码 4 登录5 卸载 安装环境:Win10 64位 软件版本:MySQL 5.7.24 解压版 1 下载 点击链接 进入如下界面 ❗️注意: 我们一般不会选择最新…