解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题

2025-02-28 17:50

本文主要是介绍解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题》在Spring开发中,@Autowired注解常用于实现依赖注入,它可以应用于类的属性、构造器或setter方法上,然...

在 Spring 开发中,@Autowired 注解常用于实现依赖注入。它可以应用于类的 属性构造器setter 方法 上。然而,当 @Autowired 注解在 属性 上使用时,IntelliJ IDEA 等 IDE 会给出 Field injection is not recommended 的警告,而在 setter 方法 上使用 @Autowired 时却不会出现这个警告。

1. 为什么 @Autowired 在属性上被警告?

1.1 China编程隐式依赖注入

@Autowired 注解应用于类的 属性 上时,Spring 会直接注入该属性,而不通过构造函数或 setter 方法显式地传递依赖项。

这种注入方式称为 字段注入(Field Injection)。

字段注入 的缺点主要体现在以下几个方面:

1.隐式依赖

  • 通过字段注入,类的依赖关系是隐式的,无法在类的构造器或方法中显式地看到这些依赖。相对而言,构造器注入setter 注入 可以使依赖关系更加明确。
  • 由于字段依赖是隐式注入的,开发者很难在不查看容器配置的情况下,快速了解一个类的所有依赖项。

2.难以进行单元测试

  • 字段注入的属性是隐式注入的,无法通过构造函数或 setter 方法显式传递。在单元测试中,手动注入php模拟(mock)对象时,需要通过反射或者测试框架自动注入,这增加了测试的复杂性。
  • 与此相比,构造器注入和 setter 注入会使依赖关系显式可见,能够更方便地进行 单元测试

3.违反依赖倒置原则(DIP)

  • 依赖倒置原则 中,依赖关系应该通过 接口抽象 进行注入,而不应该在类内部直接依赖于具体的实现。
  • 字段注入使得类的依赖更加隐式,可能会增加代码的耦合性。

1.2 IDE 的警告:Field injection is not recommended

IntelliJ IDEA 等 IDE 会根据这些设计缺点发出警告,提示 @Autowired 注解不推荐使用在属性上。

字段注入的方式可能会导致代码的可维护性差,容易出现一些潜在问题(如不清晰的依赖关系和难以测试的代码)。

2. 为什么 @Autowired 在 setter 方法上不被警告?

@Autowired 用于 setter 方法 时,Spring 会通过 setter 注入 方式将依赖项注入到对象的属性中。

与字段注入不同,setter 注入方式具有以下优势:

2.1 显式依赖注入

显式依赖关系:使用 setter 方法注入,开发者可以明确看到类所依赖的组件。通过查看类的 setter 方法,其他开发者可以轻松理解该类的依赖关系。

public class MyService {
    private MyRepository repository;
    
    @Autowired
    public void setRepository(MyRepository repository) {
        this.repository = repository;
    }
}

符合依赖注入的设计原则:通过构造函数或 setter 方法注入依赖项,可以使类的依赖关系更加清晰,符合面向对象设计中的 依赖注入单一职责原则

2.2 可选的依赖注入

setter 注入适用于一些 可选依赖 的场景。如果某个依赖是可选的,可以通过 setter 方法来灵活注入,而不需要在构造器中强制要求依赖项的传入js

@Autowired
public void setOptionalDependency(Optional<Dependency> dependency) {
    this.dependency = dependency.orElse(null);
}

2.3 易于测试

  • 由于 setter 方法可以手动设置对象的依赖,因此它可以使单元测试变得更简单。
  • 你可以通过 setter 方法为对象注入模www.chinasem.cn拟(mock)依赖项,而不需要通过反射等复杂手段。
MyService myService = new MyService();
myService.setRepository(mockRepository);

3. 构造器注入 vs 字段注入 vs Setter 注入

3.1 构造器注入(推荐)

构造器注入最推荐的依赖注入方式,它具有以下优势:

  • 强制依赖关系:通过构造器传递依赖项,可以确保所有的依赖项在对象创建时就已经被正确地注入。
  • 不可变性:构造器注入使得依赖项在对象创建时就被初始化,避免了运行时更改依赖项。
  • 易于测试:构造器注入使得所有的依赖项在构造时就显式提供,便于进行单元测试。
public class MyService {
    private final MyRepository repository;
    
    @Autowired
    public MyService(MyRepository repository) {
        this.repository = repository;
    }
}

3.2 Setter 注入(次推荐)

Setter 注入 是一个灵活的选择,适用于依赖关系较为可选或后期可更改的场景。它具有以下特点:

  • 灵活性:可以在对象创建后修改依赖项。
  • 适用于可选依赖:如果某些依赖项是可选的,setter 注入能够方便地管理。
public class MyService {
    private MyRepository repository;

    @Autowired
    public void setRepository(MyRepository repository) {
        this.repository = repository;
    }
}

3.3 字段注入(不推荐)

字段注入 是最简单的注入方式,但并不推荐使用,原因已在前面提到。字段注入具有以下缺点:

  • 不清晰的依赖关系:依赖项通过字段注入,难以通过构造器或 setter 明确看到类的依赖。
  • 难以测试:无法通过构造函数直接注入模拟对象,增加了单元测试的难度。
public class MyService {
    @Autowired
    private MyRepository repository;
}

4. 总结

  • 字段注入不推荐,因为它将依赖关系隐藏在字段中,难以清晰表达依赖项,增加了测试的复杂性。
  • 推荐使用构造器注入,它提供了最强的类型安全性和不可变性,增强了代码的可维护性和测试性。
  • Setter 注入适用于可选依赖,但在依赖较多时容易导致依赖关系变得模糊,因此需要谨慎使用。

总体而言,使用构造器注入和 setter 注入能够使代码更清晰、易于维护,同时支持更好的单元测试。

如果 IDE 提示 Field injection is not recommended,这意味着你可以考虑改用构造器注入或 setter 注入,以便提升代码质量。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持China编程(www.chinasem.cn)。

这篇关于解读为什么@Autowired在属性上被警告,在setter方法上不被警告问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153587

相关文章

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

JavaScript中的高级调试方法全攻略指南

《JavaScript中的高级调试方法全攻略指南》什么是高级JavaScript调试技巧,它比console.log有何优势,如何使用断点调试定位问题,通过本文,我们将深入解答这些问题,带您从理论到实... 目录观点与案例结合观点1观点2观点3观点4观点5高级调试技巧详解实战案例断点调试:定位变量错误性能分

Python中 try / except / else / finally 异常处理方法详解

《Python中try/except/else/finally异常处理方法详解》:本文主要介绍Python中try/except/else/finally异常处理方法的相关资料,涵... 目录1. 基本结构2. 各部分的作用tryexceptelsefinally3. 执行流程总结4. 常见用法(1)多个e

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法

《JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法》:本文主要介绍JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法,每种方法结合实例代码给大家介绍的非常... 目录引言:为什么"相等"判断如此重要?方法1:使用some()+includes()(适合小数组)方法2

深入浅出Spring中的@Autowired自动注入的工作原理及实践应用

《深入浅出Spring中的@Autowired自动注入的工作原理及实践应用》在Spring框架的学习旅程中,@Autowired无疑是一个高频出现却又让初学者头疼的注解,它看似简单,却蕴含着Sprin... 目录深入浅出Spring中的@Autowired:自动注入的奥秘什么是依赖注入?@Autowired

504 Gateway Timeout网关超时的根源及完美解决方法

《504GatewayTimeout网关超时的根源及完美解决方法》在日常开发和运维过程中,504GatewayTimeout错误是常见的网络问题之一,尤其是在使用反向代理(如Nginx)或... 目录引言为什么会出现 504 错误?1. 探索 504 Gateway Timeout 错误的根源 1.1 后端

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据