前言

这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱

一. 问题描述

公司项目闲下来了之后,我就开始整理之前写过的代码,发现每个Autowired下面都有警告,**Field injection is not recommended(不建议使用字段注入)**这是什么意思呢?

请添加图片描述

二. 警告原因和如何去除

百度了一圈,以下是我总结的问题答案

虽然 @Autowired 是 Spring Boot 中最常用的依赖注入方式之一,但是在实际开发中,建议尽量避免使用 @Autowired,而是使用构造函数注入或者 @Resource 注解注入。

以下是使用 @Autowired 存在的一些问题:

  1. 不够明确:在使用 @Autowired 进行依赖注入时,Spring 会自动根据类型来匹配 Bean,如果存在多个类型相同的 Bean,就会产生歧义。此时,需要使用 @Qualifier 注解或者 @Primary 注解来指定具体的 Bean。但是,这种方式不够明确,容易出现错误。

  2. 难以测试:使用 @Autowired 进行依赖注入时,需要在测试中手动创建 Bean,并将其注入到测试类中。这种方式比较麻烦,而且容易出现错误。

  3. 无法保证依赖注入的顺序:在使用 @Autowired 进行依赖注入时,Spring 会根据 Bean 的创建顺序来注入依赖,这种方式无法保证依赖注入的顺序。

因此,在实际开发中,建议使用构造函数注入或者 @Resource 注解注入。这种方式更加明确、易于测试,并且可以保证依赖注入的顺序,所以idea不建议使用Autowired注入了。

例如,使用构造函数注入的方式可以这样写:

@Service
public class UserService {
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    // ...
}

或者使用 @Resource 注解注入的方式可以这样写:

@Service
public class UserService {
    @Resource
    private UserRepository userRepository;

    // ...
}

这些方式都可以避免使用 @Autowired 带来的警告问题。

三. 个人的收获和解决方案

3. 1 个人感受

参考了很多个文章之后,我不在使用autowired对我来说使用autowired最大的问题是会写出很多个循环依赖出来,虽然Spring 使用了三级缓存来处理循环依赖,项目也能够正常运行,但是这样会导致很多循环依赖问题我们发现不了,写出很多不规范的代码。每个模块之间应该是分层的,每个模块、类或方法应该只负责一个明确的功能或任务,遵循单一职责

像以下循环依赖的报错,使用autowired就能够解决

请添加图片描述

以上是我的收获,不知道有没有理解错误的地方,希望大家指出

3.2 通过构造函数解决警告问题

为了消除警告,避免写出循环依赖的代码,我就使用了构造函数注入,以下是我项目中使用的方式,通过@RequiredArgsConstructor可以减少很多代码

@RequiredArgsConstructor是Lombok框架中的注解之一,用于自动生成一个包含所有必需参数的构造函数。它可以帮助开发人员减少代码量,避免手动编写构造函数。使用@RequiredArgsConstructor注解时,Lombok会自动检测类中所有被声明为final的字段,并将其作为构造函数的参数。生成的构造函数将使用这些参数来初始化字段。

例如,下面是一个使用@RequiredArgsConstructor注解:

@RequiredArgsConstructor
public class MyService {
    private final MyRepository myRepository;
    private final MyLogger myLogger;

    // ...
}

@RequiredArgsConstructor注解会自动生成一个构造函数,该构造函数包含两个参数:myRepositorymyLogger。这两个参数都是被声明为final的字段,因此它们将被用于初始化相应的字段。

生成的构造函数等效于以下代码:

public class MyService {
    private final MyRepository myRepository;
    private final MyLogger myLogger;

    public MyService(MyRepository myRepository, MyLogger myLogger) {
        this.myRepository = myRepository;
        this.myLogger = myLogger;
    }

    // ...
}

使用@RequiredArgsConstructor注解可以让开发人员更快地编写代码,并避免手动编写构造函数。将字段声明为final,以确保不可变性和线程安全性。

四. 小知识

4.1 使用@Autowired还会出现循环依赖的问题么

使用 @Autowired 仍然可能会出现循环依赖的问题。

Spring 容器在初始化时会先实例化所有的 bean,然后再进行依赖注入。如果 A bean 依赖了 B bean,而 B bean 又依赖了 A bean,就会出现循环依赖的问题。为了解决这个问题,Spring 使用了三级缓存来处理循环依赖。当容器在初始化 A bean 时,如果发现它依赖了 B bean,就会先创建一个 A bean 的代理对象,然后将代理对象放入第一级缓存中。接着容器会创建 B bean,并将其注入到 A bean 的代理对象中。最后再将 A bean 的代理对象注入到 B bean 中。但是,如果循环依赖的链条过长,就有可能导致 Spring 容器无法解决循环依赖的问题,此时就会抛出 BeanCurrentlyInCreationException 异常。因此,在使用 @Autowired 进行依赖注入时,需要注意避免出现循环依赖的情况。

4.2 @Autowired 和 @Resource区别

  • @Autowired 是 Spring 框架的注解,而 @Resource 是 JavaEE 的注解。
  • @Autowired 默认按照类型进行匹配,如果有多个同类型的 bean,则可以通过 @Qualifier 指定具体的 bean 名称。而 @Resource 默认按照名称进行匹配,如果名称匹配不到,则可以通过 name 属性指定具体的 bean 名称。
  • @Autowired 可以用在构造方法、setter 方法、字段上,而 @Resource 只能用在字段上。
  • @Autowired 是 Spring 框架的特有功能,而 @Resource 是 JavaEE 的标准功能,在使用时需要注意兼容性问题。
  • 都可以用于依赖注入

作者:神的孩子都在歌唱
本人博客:https://blog.csdn.net/weixin_46654114
转载说明:务必注明来源,附带本人博客连接。

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐