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

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

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

结构器注入

如下所示,运用结构器注入,能够将属性字段设置为final,在Aservice进行实例化时,BService目标有必要得提早初始化完结,所以运用结构器注入,能够确保被注入的目标必定不为null。结构器注入适用于目标之间强依靠的场景,可是无法处理的循环依靠问题(由于有必要互相依靠对方初始化完结,当然会产生抵触无法处理)。关于循环依靠,引荐阿里的一篇文章 一文详解Spring Bean循环依靠。

@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目标不存在,直接跳过注入,不会报错。

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

Field注入

一眼看去,Field注入简练美观,被我们普遍许多运用。Spring容器会在目标实例化完结之后,经过反射设置需要注入的的字段。

@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团队强推的仍是结构办法注入

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

总结

在Spring中运用依靠注入时,首选结构办法注入,尽管其无法处理循环依靠问题,可是当呈现循环依靠时,首选应该考虑的是是否代码结构设计呈现问题了,当然,也不排除有必要要循环依靠的场景,此刻字段注入也有用武之地。

最后想说的是,平常在运用IDEA的过程中,可能会有一些下划线或飘黄提示,假如多细心调查,能够学习到许多他人现已总结好的最佳实践经验,有助于自己代码功底的提高,共勉!

参考文献:

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

StackOverFlow关于防止运用字段注入的评论:stackoverflow.com/questions/3…