ROBlackSnail
ROBlackSnail

Reputation: 541

Spring - Dependency Injection - which takes precedence?

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'

Upvotes: 5

Views: 2470

Answers (1)

M. Deinum
M. Deinum

Reputation: 125252

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.

Upvotes: 6

Related Questions