Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autowiring two beans implementing same interface - how to set default bean to autowire?

People also ask

Can we use two beans in one interface?

You can use @Primary to give higher preference to a bean when there are multiple beans of the same type. Since we have multiple beans Car and Bike for the Vehicle type, we can use @Primary annotation to resolve the conflict. Suppose you want Spring to inject the Car bean in place of Vehicle interface.

What type of Spring exception is raised when two or more bean implementing that interface in the context?

NoUniqueBeanDefinitionException. Another similar cause for the bean creation exception is Spring trying to inject a bean by type, namely by its interface, and finding two or more beans implementing that interface in the context.

What is the default mode of @autowired?

The default mode of the @Autowired is byType .

Can I use @autowired in interface?

If you try to use @Autowired on an interface, the Spring framework would throw an exception as it won't be able to decide which implementation class to use.


I'd suggest marking the Hibernate DAO class with @Primary, i.e. (assuming you used @Repository on HibernateDeviceDao):

@Primary
@Repository
public class HibernateDeviceDao implements DeviceDao

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

Also, rather than using @Autowired @Qualifier, I find it more elegant to use @Resource for picking specific beans, i.e.

@Resource(name="jdbcDeviceDao")
DeviceDao deviceDao;

What about @Primary?

Indicates that a bean should be given preference when multiple candidates are qualified to autowire a single-valued dependency. If exactly one 'primary' bean exists among the candidates, it will be the autowired value. This annotation is semantically equivalent to the <bean> element's primary attribute in Spring XML.

@Primary
public class HibernateDeviceDao implements DeviceDao

Or if you want your Jdbc version to be used by default:

<bean id="jdbcDeviceDao" primary="true" class="com.initech.service.dao.jdbc.JdbcDeviceDao">

@Primary is also great for integration testing when you can easily replace production bean with stubbed version by annotating it.


For Spring 2.5, there's no @Primary. The only way is to use @Qualifier.


The use of @Qualifier will solve the issue.
Explained as below example : 
public interface PersonType {} // MasterInterface

@Component(value="1.2") 
public class Person implements  PersonType { //Bean implementing the interface
@Qualifier("1.2")
    public void setPerson(PersonType person) {
        this.person = person;
    }
}

@Component(value="1.5")
public class NewPerson implements  PersonType { 
@Qualifier("1.5")
    public void setNewPerson(PersonType newPerson) {
        this.newPerson = newPerson;
    }
}

Now get the application context object in any component class :

Object obj= BeanFactoryAnnotationUtils.qualifiedBeanOfType((ctx).getAutowireCapableBeanFactory(), PersonType.class, type);//type is the qualifier id

you can the object of class of which qualifier id is passed.