How does Spring autowire by name when more than one matching bean is found?

Spring

Spring Problem Overview


Suppose I have interfaces such as these:

interface Country {}
class USA implements Country {}
class UK implements Country ()

And this snippet of configuration xml:

<bean class="USA"/>
<bean id="country" class="UK"/>
<bean id="main" class="Main"/>

How can I control which dependency is autowired below? I'd like the UK one.

class Main {
    private Country country;
    @Autowired
    public void setCountry(Country country) {
        this.country = country;
    }
}

I am using Spring 3.0.3.RELEASE.

Spring Solutions


Solution 1 - Spring

This is documented in section 3.9.3 of the Spring 3.0 manual:

>For a fallback match, the bean name is considered a default qualifier value.

In other words, the default behaviour is as though you'd added @Qualifier("country") to the setter method.

Solution 2 - Spring

You can use the @Qualifier annotation

From here

Fine-tuning annotation-based autowiring with qualifiers

Since autowiring by type may lead to multiple candidates, it is often necessary to have more control over the selection process. One way to accomplish this is with Spring's @Qualifier annotation. This allows for associating qualifier values with specific arguments, narrowing the set of type matches so that a specific bean is chosen for each argument. In the simplest case, this can be a plain descriptive value:

class Main {
    private Country country;
    @Autowired
    @Qualifier("country")
    public void setCountry(Country country) {
        this.country = country;
    }
}

This will use the UK add an id to USA bean and use that if you want the USA.

Solution 3 - Spring

Another way of achieving the same result is to use the @Value annotation:

public class Main {
     private Country country;

     @Autowired
     public void setCountry(@Value("#{country}") Country country) {
          this.country = country;
     }
}

In this case, the "#{country} string is an Spring Expression Language (SpEL) expression which evaluates to a bean named country.

Solution 4 - Spring

in some case you can use annotation @Primary.

@Primary
class USA implements Country {}

This way it will be selected as the default autowire candididate, with no need to autowire-candidate on the other bean.

for mo deatils look at Autowiring two beans implementing same interface - how to set default bean to autowire?

Solution 5 - Spring

One more solution with resolving by name:

@Resource(name="country")

It uses javax.annotation package, so it's not Spring specific, but Spring supports it.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionManiganda PrakashView Question on Stackoverflow
Solution 1 - SpringskaffmanView Answer on Stackoverflow
Solution 2 - SpringPaul WhelanView Answer on Stackoverflow
Solution 3 - SpringRicardo VeguillaView Answer on Stackoverflow
Solution 4 - SpringМихаил ДмитряхаView Answer on Stackoverflow
Solution 5 - SpringthemeView Answer on Stackoverflow