IDEA-Vorschlag: Verwenden Sie @Autowire nicht für Felder!

Wenn Sie IDEA zum Schreiben von Spring-bezogenen Projekten verwenden und die @Autowired-Annotation auf dem Feld verwenden, wird immer eine Wellenlinienaufforderung angezeigt: Feldeinspritzung wird nicht empfohlen. Nani? Ich benutze es jeden Tag, daher empfehle ich es nicht, also werde ich es mir heute ansehen.

Wie wir alle wissen, gibt es in Spring drei optionale Injektionsmethoden: Konstruktorinjektion, Setter-Methodeninjektion und Feldinjektion. Schauen wir uns zunächst die Verwendungsszenarien dieser drei Injektionsmethoden an.

Konstruktorinjektion

Wie unten gezeigt, können Sie mithilfe der Konstruktorinjektion das Attributfeld auf „final“ setzen. Wenn AService instanziiert wird, muss das BService-Objekt im Voraus initialisiert werden, sodass mithilfe der Konstruktorinjektion sichergestellt werden kann, dass das injizierte Objekt nicht null sein darf . Die Konstruktorinjektion eignet sich für Szenarien mit starken Abhängigkeiten zwischen Objekten, das Problem der zirkulären Abhängigkeiten kann jedoch nicht gelöst werden (da sie für die vollständige Initialisierung aufeinander angewiesen sind, können Konflikte natürlich nicht gelöst werden). Bezüglich zirkulärer Abhängigkeiten empfehle ich einen Artikel von Ali, in dem die zirkulären Abhängigkeiten von Spring Bean ausführlich erläutert werden .

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

Setter-Methode-Injektion

Wenn Sie die Setter-Methode für die Injektion verwenden, ruft Spring die Setter-Methode auf, um Abhängigkeiten zu injizieren, nachdem der Standardkonstruktor ohne Argumente ausgeführt wurde, um das Bean-Objekt zu instanziieren. Verwenden Sie zum Injizieren die Setter-Methode und requiredsetzen Sie das Attribut auf false. Wenn das injizierte Bean-Objekt nicht vorhanden ist, wird die Injektion direkt übersprungen und es wird kein Fehler gemeldet.

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

Feldinjektion

Auf den ersten Blick ist Field einfach und schön und wird von allen häufig verwendet. Der Spring-Container legt die Felder fest, die nach Abschluss der Objektinstanziierung durch Reflektion eingefügt werden müssen.

@Service
public class AService {
    @Autowired
    private  BService bService;
}

Warum IDEA die Verwendung der Feldinjektion nicht empfiehlt

Nachdem ich verschiedene Quellen konsultiert hatte, fand ich die folgenden wichtigen Gründe:

  • Dies kann zu einer Nullzeiger-Ausnahme führen : Wenn Sie nicht den Spring-Container zum Erstellen eines Objekts verwenden, sondern direkt den Konstruktor ohne Argumente zum Erstellen eines Objekts verwenden, führt die Verwendung des injizierten Objekts zu einem Nullzeiger.
  • 不能使用final修饰字段:不使用final修饰,会导致类的依赖可变,进而可能会导致一些不可预料的异常。通常情况下,此时可以使用构造方法注入来声明强制依赖的Bean,使用Setter方法注入来声明可选依赖的Bean。
  • 可能更容易违反单一职责原则:个人认为这点是一个很重要的原因。因为使用字段注入可以很轻松的在类上加入各种依赖,进而导致类的职责过多,但是往往开发者对此不能轻易察觉。而如果使用构造方法注入,当构造方法的参数过多时,就会提醒你,你该重构这个类了。
  • 不利于写单元测试:在单元测试中,使用Field注入,必须使用反射的方式来Mock依赖对象。

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

Spring官方的态度

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

Konstruktor-Injektion oder Setter-Injektion

总结

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

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

参考文献:

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

StackOverFlow-Diskussion zur Vermeidung der Feldinjektion: stackoverflow.com/questions/3…

Supongo que te gusta

Origin juejin.im/post/7261509144238473277
Recomendado
Clasificación