spring 和 idea 建议不要使用 @Autowired注解
- 一. 问题描述
- 二. 警告原因和如何去除
- 三. 个人的收获和解决方案
- 3. 1 个人感受
- 3.2 通过构造函数解决警告问题
- 四. 小知识
- 4.1 使用@Autowired还会出现循环依赖的问题么
- 4.2 @Autowired 和 @Resource区别
前言
这是我在这个网站整理的笔记,有错误的地方请指出,关注我,接下来还会持续更新。 作者:神的孩子都在歌唱
一. 问题描述
公司项目闲下来了之后,我就开始整理之前写过的代码,发现每个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 的标准功能,在使用时需要注意兼容性问题。
- 都可以用于依赖注入
作者:神的孩子都在歌唱
本人博客:https://blog.csdn.net/weixin_46654114
转载说明:务必注明来源,附带本人博客连接。