spring 和 idea 建议不要使用 @Autowired注解的原因解析
作者:神的孩子都在歌唱
前言
这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱
一. 问题描述
公司项目闲下来了之后,我就开始整理之前写过的代码,发现每个Autowired下面都有警告,**Field injection is not recommended(不建议使用字段注入)**这是什么意思呢?
二. 警告原因和如何去除
百度了一圈,以下是我总结的问题答案
虽然 @Autowired
是 Spring Boot 中最常用的依赖注入方式之一,但是在实际开发中,建议尽量避免使用 @Autowired
,而是使用构造函数注入或者 @Resource
注解注入。
以下是使用 @Autowired
存在的一些问题:
- 不够明确:在使用
@Autowired
进行依赖注入时,Spring 会自动根据类型来匹配 Bean,如果存在多个类型相同的 Bean,就会产生歧义。此时,需要使用@Qualifier
注解或者@Primary
注解来指定具体的 Bean。但是,这种方式不够明确,容易出现错误。 - 难以测试:使用
@Autowired
进行依赖注入时,需要在测试中手动创建 Bean,并将其注入到测试类中。这种方式比较麻烦,而且容易出现错误。 - 无法保证依赖注入的顺序:在使用
@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
注解会自动生成一个构造函数,该构造函数包含两个参数:myRepository
和myLogger
。这两个参数都是被声明为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 的标准功能,在使用时需要注意兼容性问题。
- 都可以用于依赖注入
到此这篇关于spring 和 idea 建议不要使用 @Autowired注解的文章就介绍到这了,更多相关spring和 idea 不使用 @Autowired注解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!