英文:
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
以下是翻译好的内容:
首先,不要做类似那样的事情。
话虽如此,接下来会按顺序发生以下情况:
- 它将使用一个
FortuneService
的实例调用构造函数,因为在其他任何事情发生之前,需要先构造该对象。 - 它将用一个
FortuneService
的实例注入带有@Autowired
注解的字段。 - 它将用一个
FortuneService
的实例调用带有@Autowired
注解的方法。
现在,根据FortuneService
的作用域,它将注入一个单例(默认)或创建一个新实例(当bean的作用域是原型时)。
注意: 可以从 AutowiredAnnotationBeanPostProcessor
的源代码中推断出顺序。构造函数被调用是合理的,但字段与方法的顺序来自于 buildAutowiringMetadata
方法。它首先检测字段,然后是方法。
英文:
For starters don't do things like that.
That being said the following will happen, in order:
- It will call the constructor with an instance of
FortuneService
, because the object needs to be constructed first, before anything else can happen. - It will inject the fields annotated with
@Autowired
with an instance ofFortuneService
- It will call the methods annotated with
@Autowired
with an instance ofFortuneService
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论