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

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.

This question is related to spring

The answer is


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?


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.


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.


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.