Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

spring

People also ask

Can you Autowire by type when more than one bean?

3. Autowiring using property type. Allows a property to be autowired if exactly one bean of property type exists in the container. If more than one exists, it's a fatal exception is thrown, which indicates that you may not used byType autowiring for that bean.

How do you Autowire a particular bean if more than one bean of the same class type?

The default autowiring is by type, not by name, so when there is more than one bean of the same type, you have to use the @Qualifier annotation.

What will happen if multiple objects for required type are found for Autowiring?

2) byType autowiring mode It internally uses setter injection. In this case, it works fine because you have created an instance of B type. It doesn't matter that you have different bean name than reference name. But, if you have multiple bean of one type, it will not work and throw exception.


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.


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.


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.


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?


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.