Field injection is not recommended

文章目录

  • 1. 引言
  • 2. 不推荐使用@Autowired的原因
  • 3. Spring提供了三种主要的依赖注入方式
    • 3.1. 构造函数注入(Constructor Injection)
    • 3.2. Setter方法注入(Setter Injection)
    • 3.3. 字段注入(Field Injection)
  • 4. 推荐方案
  • 5. 参考博客

1. 引言

Field injection is not recommended

意思就是不推荐使用字段注入的方式,不是不推荐@Autowired注解,以前为了简便就直接使用
@Resource代替,程序员都在不断追求完美。。。 接下来我们实实在在的分析一下为啥不推荐,以及到底推荐那种方式注入。

2. 不推荐使用@Autowired的原因

不推荐使用@Autowired进行字段注入的原因有以下几点:

  1. 紧耦合性(Tight Coupling):字段注入将依赖关系直接注入到类的字段上,导致类与依赖之间产生紧密的耦合。这使得代码难以修改和扩展,并且增加了对具体实现的依赖性。

  2. 隐藏依赖关系(Hidden Dependencies):字段注入隐藏了类的依赖关系,使代码不够透明和可读。读取代码时无法立即知道类所依赖的其他组件或服务。

  3. 单元测试困难(Difficult Unit Testing):由于字段注入需要依赖容器来自动注入依赖项,导致在编写单元测试时必须依赖完整的容器环境。这增加了测试的复杂性,并且可能会导致测试变慢或不稳定。

  4. 难以发现依赖问题(Dependency Issues):字段注入使得依赖可以在运行时更改,这增加了代码维护的复杂性。同时,如果依赖项没有正确配置或不存在,就会在运行时出现错误,而不是在编译时就能发现。

相比之下,构造器注入(Constructor Injection)或Setter方法注入(Setter Injection)提供了更好的可测试性、可维护性和代码清晰度。它们明确列出了类所需的依赖项,并使得依赖关系更加透明和易于理解。这些方法也更容易进行单元测试,且不需要依赖完整的容器环境。

3. Spring提供了三种主要的依赖注入方式

3.1. 构造函数注入(Constructor Injection)

通过构造函数将依赖项传递给目标类。这种方式明确声明了类所需的依赖项,并且使得类的实例在创建时就具备了必要的依赖关系。示例代码如下:

@Component
public class SLFBClient {private final DataSourceFactory dataSourceFactory;/*** @Autowired 从spring4.3开始可以省略*/
//    @Autowiredpublic SLFBClient(DataSourceFactory dataSourceFactory) {this.dataSourceFactory = dataSourceFactory;}}

3.2. Setter方法注入(Setter Injection)

通过Setter方法设置依赖项。这种方式允许使用默认构造函数创建类的实例,然后通过Setter方法来动态设置依赖项。示例代码如下:

@Component
public class SLFBClient {private  DataSourceFactory dataSourceFactory;/*** @Autowired 从spring4.3开始可以省略*/
//    @Autowiredpublic void setDataSourceFactory(DataSourceFactory dataSourceFactory) {this.dataSourceFactory = dataSourceFactory;}
}

3.3. 字段注入(Field Injection)

通过直接将依赖项注入到类的字段上。这种方式最简洁,但也最不推荐使用(在之前的回答中已经详细解释了原因)。示例代码如下:

@Component
public class SLFBClient {//    @Autowired
//    @Resource@Injectprivate DataSourceFactory dataSourceFactory;}

@Autowired、@Resource和@Inject是用于依赖注入的常见注解,它们在使用方式和一些细节上有一些区别。

  1. @Autowired:

    • 来自Spring框架。
    • 默认按照类型(byType)进行依赖注入,会尝试将匹配的bean自动注入到目标字段、构造函数或方法参数中。
    • 可以与@Qualifier一起使用,通过指定bean的名称或限定符来进一步指定要注入的bean。
    • @Autowired是非强制性的,可以在某些情况下将依赖项标记为可选。
  2. @Resource:

    • Java EE的标准注解,也可以被Spring框架支持。
    • 默认按照名称(byName)进行依赖注入,通过指定bean的名称来解析并注入匹配的bean
    • 可以使用name属性指定要注入的bean的名称。
    • @Resource是强制性的,要求找到匹配的bean进行注入,否则会抛出异常。
  3. @Inject:

    • Java CDI(Contexts and Dependency Injection)规范的一部分,可以由Java EE和一些其他框架(如Spring)支持。
    • 默认按照类型(byType)进行依赖注入,使用与@Autowired类似的机制。
    • 不支持required属性,即所有注入都被视为必需的。
    • 可以与@Qualifier一起使用,通过指定bean的名称或限定符来进一步指定要注入的bean

总结:

  • @AutowiredSpring特有的注解,默认按类型进行依赖注入。
  • @ResourceJava EE的标准注解,可被Spring支持,默认按名称进行依赖注入。
  • @InjectJava CDI规范的注解,也可被Spring等框架支持,默认按类型进行依赖注入。
  • 三个注解都可以与@Qualifier一起使用来指定具体要注入的bean
  • @Autowired@Inject在功能上相似,而@Resource功能稍有不同,但它们通常可以互相替代使用。

需要注意的是,具体在Spring中使用哪个注解,可以根据项目的需求、框架的支持以及个人偏好来决定。

4. 推荐方案

使用构造器注入的好处:

  • 保证依赖不可变(final关键字)
  • 保证依赖不为空(省去了我们对其检查)
  • 保证返回客户端(调用)的代码的时候是完全初始化的状态
  • 避免了循环依赖
  • 提升了代码的可复用性

推荐使用Lombok中的@RequiredArgsConstructor注解

@Component
@RequiredArgsConstructor
public class SLFBClient {private final DataSourceFactory dataSourceFactory;}

接下来我们探讨一下Lombok@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsContructor三个注解

  1. @NoArgsConstructor:
    • 自动生成一个无参构造函数。
    • 适用于不需要传入参数的情况。
import lombok.NoArgsConstructor;@NoArgsConstructor
public class MyClass {// Fields and methods
}

2. @RequiredArgsConstructor:

  • 自动生成一个包含所有被标记为final和@NonNull的字段的构造函数。
  • 适用于只关注部分字段并确保这些字段非空的情况。
import lombok.NonNull;
import lombok.RequiredArgsConstructor;@RequiredArgsConstructor
public class MyClass {private final String name;@NonNullprivate final Integer age;// Other fields and methods
}
  1. @AllArgsConstructor:
    • 自动生成一个包含所有类字段的构造函数。
    • 适用于需要一次性传递所有字段值的情况。
import lombok.AllArgsConstructor;@AllArgsConstructor
public class MyClass {private String name;private int age;// Other fields and methods
}

5. 参考博客

Field Dependency Injection Considered Harmful

Field injection is not recommended(Spring团队不推荐使用Field注入)

【Spring】浅谈spring为什么推荐使用构造器注入

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

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

相关文章

计算机视觉五大核心研究任务全解:分类识别、检测分割、人体分析、三维视觉、视频分析

目录 一、引言1.1 计算机视觉的定义1.1.1 核心技术1.1.2 应用场景 1.2 历史背景及发展1.2.1 1960s-1980s: 初期阶段1.2.2 1990s-2000s: 机器学习时代1.2.3 2010s-现在: 深度学习的革命 1.3 应用领域概览1.3.1 工业自动化1.3.2 医疗图像分析1.3.3 自动驾驶1.3.4 虚拟现实与增强现…

山东布谷科技直播软件开发WebRTC技术:建立实时通信优质平台

在数字化的时代,实时通信成为了人们远程交流的主要方式,目前市场上也出现了很多带有实时通信交流的软件,实时通信符合人们现在的需求,所以在直播软件开发过程中,开发者也运用了实时通信技术为直播软件加入了实时通信的…

【计算机视觉|生成对抗】生成对抗网络(GAN)

本系列博文为深度学习/计算机视觉论文笔记,转载请注明出处 标题:Generative Adversarial Nets 链接:Generative Adversarial Nets (nips.cc) 摘要 我们提出了一个通过**对抗(adversarial)**过程估计生成模型的新框架…

2.阿里云对象存储OSS

1.对象存储概述 文件上传,是指将本地图片、视频、音频等文件上传到服务器上,可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛,我们经常发抖音、发朋友圈都用到了文件上传功能。 实现文件上传服务,需要有存储的支持…

【概念理解】STM32中的sprintf()函数

sprintf()函数 这个函数在 stdio.h中;可以将格式化的数据写入到一个字符串缓冲区中。 int sprintf(char *str, const char *format, ...);str:指向字符数组的指针,即用于存储格式化后字符串的缓冲区。format:格式化字符串&#…

(十六)大数据实战——安装使用mysql版的hive服务

前言 hive默认使用的是内嵌据库derby,Derby 是一个嵌入式数据库,可以轻松地以库的形式集成到应用程序中。它不需要独立的服务器进程,所有的数据存储在应用程序所在的文件系统中。为了支持hive服务更方便的使用,我们使用mysql数据…

【实战】十一、看板页面及任务组页面开发(一) —— React17+React Hook+TS4 最佳实践,仿 Jira 企业级项目(二十三)

文章目录 一、项目起航:项目初始化与配置二、React 与 Hook 应用:实现项目列表三、TS 应用:JS神助攻 - 强类型四、JWT、用户认证与异步请求五、CSS 其实很简单 - 用 CSS-in-JS 添加样式六、用户体验优化 - 加载中和错误状态处理七、Hook&…

c语言每日一练(8)

前言:每日一练系列,每一期都包含5道选择题,2道编程题,博主会尽可能详细地进行讲解,令初学者也能听的清晰。每日一练系列会持续更新,暑假时三天之内必有一更,到了开学之后,将看学业情…

【javaweb】学习日记Day1 - HTML CSS入门

目录 一、图片标签 ① 绝对路径 1.绝对磁盘路径 2.绝对网络路径 ② 相对路径 (推荐) 二、标题标签 三、水平线标签 四、标题样式 1、CSS引入样式 ① 行内样式 ② 内嵌样式 ③ 外嵌样式 2、CSS选择器 ① 元素选择器 ② id选择器 ③…

Hadoop+Python+Django+Mysql热门旅游景点数据分析系统的设计与实现(包含设计报告)

系统阐述的是使用热门旅游景点数据分析系统的设计与实现,对于Python、B/S结构、MySql进行了较为深入的学习与应用。主要针对系统的设计,描述,实现和分析与测试方面来表明开发的过程。开发中使用了 django框架和MySql数据库技术搭建系统的整体…

Python批量给excel文件加密

有时候我们需要定期给公司外部发邮件,在自动化发邮件的时候需要对文件进行加密传输。本文和你一起来探索用python给单个文件和批量文件加密。    python自动化发邮件可参考【干货】用Python每天定时发送监控邮件。 文章目录 一、安装pypiwin32包二、定义给excel加…

【Docker】Docker使用之容器技术发展史

🎬 博客主页:博主链接 🎥 本文由 M malloc 原创,首发于 CSDN🙉 🎄 学习专栏推荐:LeetCode刷题集 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正&#xff0…

【Unity】UI的一些简单知识

Canvas 新建一个Canvas Render Mode Canvas 中有一个Render Mode(渲染模式),有三种渲染模式: Screen Space-Overlay (屏幕空间)Screen Space-Camara 、 World Space 其中,Space- Overlay是默认显示在…

数据统计与可视化的Dash应用程序

在数据分析和可视化领域,Dash是一个强大的工具,它结合了Python中的数据处理库(如pandas)和交互式可视化库(如Plotly)以及Web应用程序开发框架。本文将介绍如何使用Dash创建一个简单的数据统计和可视化应用程…

【C++学习手札】一文带你初识运算符重载

食用指南:本文在有C基础的情况下食用更佳 🍀本文前置知识: C类 ♈️今日夜电波:クリームソーダとシャンデリア—Edo_Ame江户糖 1:20 ━━━━━━️💟──────── 3:40 …

idea cannot download sources 解决方法

问题 点击class文件右上角下载源码失败 解决方案 找到idea terminal 控制台cd 至maven工程执行 mvn dependency:resolve -Dclassifiersources

【IMX6ULL驱动开发学习】04.应用程序和驱动程序数据传输和交互的4种方式:非阻塞、阻塞、POLL、异步通知

一、数据传输 1.1 APP和驱动 APP和驱动之间的数据访问是不能通过直接访问对方的内存地址来操作的,这里涉及Linux系统中的MMU(内存管理单元)。在驱动程序中通过这两个函数来获得APP和传给APP数据: copy_to_usercopy_from_user …

24届近3年上海电力大学自动化考研院校分析

今天给大家带来的是上海电力大学控制考研分析 满满干货~还不快快点赞收藏 一、上海电力大学 学校简介 上海电力大学(Shanghai University of Electric Power),位于上海市,是中央与上海市共建、以上海市管理为主的全日…

stack 、 queue的语法使用及底层实现以及deque的介绍【C++】

文章目录 stack的使用queue的使用适配器queue的模拟实现stack的模拟实现deque stack的使用 stack是一种容器适配器&#xff0c;具有后进先出&#xff0c;只能从容器的一端进行元素的插入与提取操作 #include <iostream> #include <vector> #include <stack&g…

Layui列表复选框根据条件禁用

// 禁用客服回访id有值的复选框res.data.forEach(function (item, i) {if (item.feedbackEmpId) {let index res.data[i][LAY_TABLE_INDEX];$(".layui-table tr[data-index"index"] input[typecheckbox]").prop(disabled,true);$(".layui-table tr[d…