【问题标题】:Spring - Dependency Injection - which takes precedence?Spring - 依赖注入 - 哪个优先?
【发布时间】:2020-12-28 17:45:23
【问题描述】:

我知道使用 Spring 进行依赖注入有 3 种方法:字段、setter 和构造函数注入。

但是假设我们在同一个组件中有更多的所有 3 个,就像这样:

import base.service.FortuneService;

@Component
public class FootballCoach implements Coach {
    
    //Field Injection
    @Autowired
    private FortuneService fortuneService;
    
    //setter Injection
    @Autowired
    public void setFortuneService(FortuneService fortuneService) {
        this.fortuneService = fortuneService;
    }
    //constructor Injection
    @Autowired
    public FootballCoach(FortuneService fortuneService) {
        this.fortuneService = fortuneService;
    }
}

哪个优先 - 可以这么说? Spring 会做所有 3 次并覆盖 fortuneService 字段两次吗?如果是这样,最后一个站着的是哪一个?还是只会选择一个依赖注入?

我运行上面的代码没有问题,我得到了以下日志,但我真的不知道如何阅读它们。

注意:FortuneService 是一个接口,我有一个实现它的HappyFortuneService 类。

Sep 10, 2020 11:40:44 AM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry getSingleton
FINE: Creating shared instance of singleton bean 'footballCoach'
Sep 10, 2020 11:40:44 AM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry getSingleton
FINE: Creating shared instance of singleton bean 'happyFortuneService'
Sep 10, 2020 11:40:44 AM org.springframework.beans.factory.support.ConstructorResolver createArgumentArray
FINE: Autowiring by type from bean name 'footballCoach' via constructor to bean named 'happyFortuneService'
Sep 10, 2020 11:40:44 AM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry getSingleton
FINE: Creating shared instance of singleton bean 'tennisCoach'
Sep 10, 2020 11:40:44 AM org.springframework.beans.factory.support.ConstructorResolver createArgumentArray
FINE: Autowiring by type from bean name 'tennisCoach' via constructor to bean named 'happyFortuneService'

【问题讨论】:

  • 构造函数必须优先于其他两个,因为你不能设置字段或调用任何方法。
  • "Spring 会做所有 3 个操作" 在 setter 中设置断点。那会给你答案。我认为是的。当然,真正的答案是“一开始就不要这样做
  • 在同一个对象的三个地方注入相同的东西是没有用的。
  • @Michael 好的,所以构造函数是第一个调用的,我可以理解,并且创建了一个 bean。但随后其他 2 个被调用。当字段和 setter 注入发生然后覆盖第一个 bean 时,是否会创建两个新 bean?如果有,按什么顺序?
  • 为什么不向每个块添加System.out.println() 语句(可能将字段打印为构造函数中的第一条语句)并自己查看?

标签: java spring dependency-injection


【解决方案1】:

对于初学者不要做那样的事情。

话虽如此,以下将按顺序发生:

  1. 它将使用FortuneService 的实例调用构造函数,因为需要先构造对象,然后才能发生其他任何事情。
  2. 它将用FortuneService 的实例注入带有@Autowired 注释的字段
  3. 它将调用带有@Autowired 注释的方法,实例为FortuneService

现在根据FortuneService 的范围,它将注入一个单例(默认)或创建一个新实例(当 bean 是原型范围时)。

注意: 排序可以从AutowiredAnnotationBeanPostProcessorsource 推导出来。调用构造函数是合乎逻辑的,但字段与方法的顺序来自buildAutowiringMetadata 方法。它首先检测字段,然后检测方法。

【讨论】:

  • 我正要在问题中添加这个。它位于AutowiredAnnotationBeanPostProcessor 的源代码中,并且需要首先调用构造函数的事实只是普通的 java(没有对象实例,就无法反射地设置字段或调用方法)。
  • 很好,尽管在文档中没有明确提及似乎与 Spring 不同。我想你不应该真的依赖它,所以也许他们认为这是一个隐含的细节。
猜你喜欢
  • 2020-07-12
  • 1970-01-01
  • 1970-01-01
  • 2018-11-21
  • 2012-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-06
相关资源
最近更新 更多