IDEA建议:不要在字段上使用@Autowire了!

在使用IDEA写Spring相关的项目的时候,在字段上使用@Autowired注解时,总是会有一个波浪线提示:Field injection is not recommended. 纳尼?我天天用,咋就不建议了,今天就来一探究竟。

众所周知,在Spring里面有三种可选的注入方式:构造器注入、Setter方法注入、Field注入,我们先来看下这三种注入方式的使用场景。

构造器注入

如下所示,使用构造器注入,可以将属性字段设置为final,在Aservice进行实例化时,BService对象必须得提前初始化完成,所以使用构造器注入,能够保证被注入的对象一定不为null 。构造器注入适用于对象之间强依赖的场景,但是无法解决的循环依赖问题(因为必须互相依赖对方初始化完成,当然会产生冲突无法解决)。关于循环依赖,推荐阿里的一篇文章 一文详解Spring Bean循环依赖

kotlin 复制代码
@Service
public class AService {
    private final BService bService;
​
    @Autowired  //spring framework 4.3之后可以不用在构造方法上标注@Autowired
    public AService(BService bService) {
        this.bService = bService;
    }
}

Setter 方法注入

使用Setter方法进行注入时,Spring会在执行默认的无参构造函数实例化Bean对象之后,调用Setter方法来注入依赖。使用Setter方法注入可以将 required 属性设置为 false,表示若注入的Bean对象不存在,直接跳过注入,不会报错。

typescript 复制代码
@Service
public class AService {
    private  BService bService;
​
    @Autowired(required = false)
    public void setbService(BService bService) {
        this.bService = bService;
    }
}

Field注入

一眼看去,Field注入简洁美观,被大家普遍大量使用。Spring容器会在对象实例化完成之后,通过反射设置需要注入的的字段。

kotlin 复制代码
@Service
public class AService {
    @Autowired
    private  BService bService;
}

为什么IDEA不推荐使用Field注入

经查阅各方资料,我找到了如下几个比较重要的原因:

  • 可能导致空指针异常:如果创建对象不使用Spring容器,而是直接使用无参构造方法new一个对象,此时使用注入的对象会导致空指针。
  • 不能使用final修饰字段:不使用final修饰,会导致类的依赖可变,进而可能会导致一些不可预料的异常。通常情况下,此时可以使用构造方法注入来声明强制依赖的Bean,使用Setter方法注入来声明可选依赖的Bean。
  • 可能更容易违反单一职责原则:个人认为这点是一个很重要的原因。因为使用字段注入可以很轻松的在类上加入各种依赖,进而导致类的职责过多,但是往往开发者对此不能轻易察觉。而如果使用构造方法注入,当构造方法的参数过多时,就会提醒你,你该重构这个类了。
  • 不利于写单元测试:在单元测试中,使用Field注入,必须使用反射的方式来Mock依赖对象。

那么替代方案是什么呢?其实上面已经提到了,当我们的类有强依赖于其他Bean时,使用构造方法注入;可选依赖时,使用Setter方法注入(需要自己处理可能出现的引用对象不存在的情况)。

Spring官方的态度

Spring 官方文档在依赖注入这一节其实没有讨论字段注入这种方式,重点比较了构造方法注入和Setter注入。可以看到Spring团队强推的还是构造方法注入

总结

在Spring中使用依赖注入时,首选构造方法注入,虽然其无法解决循环依赖问题,但是当出现循环依赖时,首选应该考虑的是是否代码结构设计出现问题了,当然,也不排除必须要循环依赖的场景,此时字段注入也有用武之地。

最后想说的是,平时在使用IDEA的过程中,可能会有一些下划线或飘黄提醒,如果多细心观察,可以学习到很多他人已经总结好的最佳实践经验,有助于自己代码功底的提升,共勉!

参考文献:

Spring 官方文档关于依赖注入: docs.spring.io/spring-fram...

StackOverFlow关于避免使用字段注入的讨论:stackoverflow.com/questions/3...

相关推荐
hrrrrb18 分钟前
【Spring Security】Spring Security 概念
java·数据库·spring
小信丶18 分钟前
Spring 中解决 “Could not autowire. There is more than one bean of type“ 错误
java·spring
周杰伦_Jay1 小时前
【Java虚拟机(JVM)全面解析】从原理到面试实战、JVM故障处理、类加载、内存区域、垃圾回收
java·jvm
程序员小凯5 小时前
Spring Boot测试框架详解
java·spring boot·后端
豐儀麟阁贵5 小时前
基本数据类型
java·算法
_extraordinary_5 小时前
Java SpringMVC(二) --- 响应,综合性练习
java·开发语言
程序员 Harry6 小时前
深度解析:使用ZIP流式读取大型PPTX文件的最佳实践
java
wxweven7 小时前
校招面试官揭秘:我们到底在寻找什么样的技术人才?
java·面试·校招
陈陈爱java7 小时前
新知识点背诵
java
失散137 小时前
分布式专题——39 RocketMQ客户端编程模型
java·分布式·架构·rocketmq