Handling Multiple Autowire Candidates with Spring @Qualifier
Handling multiple autowire candidates with @Primary is effective when only one primary candidate can be determined for multiple autowire candidates. When you need more control over the selection process, you can use spring @Qualifier annotation. The @Qualifier
annotation allows you to associate a given name with a specific bean type. Thus autowiring by type and by name, to narrow the autowire dependency candidates to only one.
Handle Multiple Autowire dependencies with @Qualifier
The @Qualifier
annotation may be used on a field, method or parameter as a qualifier for candidate beans when autowiring. This makes the autowiring by type and by name. Thus reducing and specifying the correct type for autowire dependency injection. In this example both MysqlMessageRepository
and InMemoryMessageRepository
beans are injected in the SellPhone
bean.
package com.memorynotfound.spring.core.autowired;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class SellPhone {
@Autowired
@Qualifier(value = "mysqlMessageRepository")
private MessageRepository mysqlMessageRepository;
@Autowired
@Qualifier(value = "inMemoryMessageRepository")
private MessageRepository inMemoryMessageRepository;
public void sendMessage(){
mysqlMessageRepository.save();
inMemoryMessageRepository.save();
}
}
We are creating two implementations of this interface, which we are autowiring in a spring bean.
package com.memorynotfound.spring.core.autowired;
public interface MessageRepository {
void save();
}
The @Repository
is a special marker annotation. When component scanning is enabled, spring will automatically pick it up and create a bean definition to make it available for autowiring.
package com.memorynotfound.spring.core.autowired;
import org.springframework.stereotype.Repository;
@Repository
public class InMemoryMessageRepository implements MessageRepository{
@Override
public void save() {
System.out.println("saving in memory");
}
}
This is the second implementation.
package com.memorynotfound.spring.core.autowired;
import org.springframework.stereotype.Repository;
@Repository
public class MysqlMessageRepository implements MessageRepository{
@Override
public void save() {
System.out.println("saving in mysql");
}
}
Enable Auto Component Scanning
We enable auto component scanning by registering the <context:component-scan/> element inside the top level <beans/> element. We provide a package name which spring will recursively scan for other components.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.memorynotfound"/>
</beans>
Testing The Application
We bootstrap the application by loading the spring xml configuration file using the ClassPathXmlApplicationContext
. Afterwards we get a reference of the SellPhone
bean on which we invoke the save()
method.
package com.memorynotfound.spring.core.autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Run {
public static void main(String... args) {
ApplicationContext xmlContext = new ClassPathXmlApplicationContext("app-config.xml");
SellPhone sellPhone = xmlContext.getBean(SellPhone.class);
sellPhone.sendMessage();
}
}
This is the produced output of the previous code. As you can see, both autowired dependencies are injected.
saving in mysql
saving in memory
I see that you used Field autowiring with Qualifier to wire the two dependencies. But how is this done using constructor autowiring?
To inject 2 beans of the same type using constructor dependency injection you can use the named @Qualifier before the argument type.
If we have same implementation class how it can be done how we can created two different instances of class and inject as bean
You can use the
@Qualifier("nameOfBean")
to indicate which implementation you want to autowire. Either using Field Injection, Setter Injection or Constructor Injection.