春 – 依赖注入 – 哪个优先?

huangapple go评论73阅读模式
英文:

Spring - Dependency Injection - which takes precedence?

问题

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

但假设我们在同一个组件中同时使用了这三种方式,就像这样:

import base.service.FortuneService;

@Component
public class FootballCoach implements Coach {
    
    // 字段注入
    @Autowired
    private FortuneService fortuneService;
    
    // setter方法注入
    @Autowired
    public void setFortuneService(FortuneService fortuneService) {
        this.fortuneService = fortuneService;
    }
    // 构造函数注入
    @Autowired
    public FootballCoach(FortuneService fortuneService) {
        this.fortuneService = fortuneService;
    }
}

哪种方式优先级更高呢?Spring会同时执行这三种方式并覆盖fortuneService字段两次吗?如果是这样,最终哪种方式会生效?还是只会选择一种依赖注入方式?

我运行了上面的代码,没有出现问题,并且得到了以下日志,但我不太清楚如何阅读它们。

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

Sep 10, 2020 11:40:44 AM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry getSingleton
FINE: 正在创建单例bean 'footballCoach' 的共享实例
Sep 10, 2020 11:40:44 AM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry getSingleton
FINE: 正在创建单例bean 'happyFortuneService' 的共享实例
Sep 10, 2020 11:40:44 AM org.springframework.beans.factory.support.ConstructorResolver createArgumentArray
FINE: 通过类型自动装配,从bean名称 'footballCoach' 到bean名称 'happyFortuneService' 的构造函数
Sep 10, 2020 11:40:44 AM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry getSingleton
FINE: 正在创建单例bean 'tennisCoach' 的共享实例
Sep 10, 2020 11:40:44 AM org.springframework.beans.factory.support.ConstructorResolver createArgumentArray
FINE: 通过类型自动装配,从bean名称 'tennisCoach' 到bean名称 'happyFortuneService' 的构造函数
英文:

I know there are 3 ways to do Dependency Injection using Spring : field, setter and constructor Injection.

But say we have more all 3 in the same Component, like so :

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;
	}
}

Which one takes precedence - so to say? Will Spring just do all 3 and overwrite the fortuneService field two times? If so, which is the last one standing? Or will only one dependency injection be chosen?

I ran the code above without problems and I got the following logs, but I don't really know how to read them.

Note: FortuneService is an interface and I have a HappyFortuneService class that implements it.

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'

答案1

得分: 5

以下是翻译好的内容:

首先,不要做类似那样的事情。

话虽如此,接下来会按顺序发生以下情况:

  1. 它将使用一个FortuneService的实例调用构造函数,因为在其他任何事情发生之前,需要先构造该对象。
  2. 它将用一个FortuneService的实例注入带有@Autowired注解的字段。
  3. 它将用一个FortuneService的实例调用带有@Autowired注解的方法。

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

注意: 可以从 AutowiredAnnotationBeanPostProcessor源代码中推断出顺序。构造函数被调用是合理的,但字段与方法的顺序来自于 buildAutowiringMetadata 方法。它首先检测字段,然后是方法。

英文:

For starters don't do things like that.

That being said the following will happen, in order:

  1. It will call the constructor with an instance of FortuneService, because the object needs to be constructed first, before anything else can happen.
  2. It will inject the fields annotated with @Autowired with an instance of FortuneService
  3. It will call the methods annotated with @Autowired with an instance of FortuneService

Now depending on the scope of the FortuneService, it will either inject a singleton (the default) or create a new instance (when the bean is prototype scoped).

NOTE: The ordering can be deduced from the source of the AutowiredAnnotationBeanPostProcessor. That the constructor is called is logical but the ordering of field vs. method is coming from the buildAutowiringMetadata method. It detects first the fields then the methods.

huangapple
  • 本文由 发表于 2020年9月10日 16:50:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/63826101.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定