In my Java spring application, I have
public class BinarySearchImpl {
@Autowired
@Qualifier("Quick")
SortAlgorithem sorter;
Log log=LogFactory.getLog(BinarySearchImpl.class);
public BinarySearchImpl(SortAlgorithem sorter) {
log.info("Binary Search Bean is created");
this.sorter=sorter;
}
SortAlgorithem
is an interface which makes my application loosely coupled:
public interface SortAlgorithem {
public int[] sort(int[] arrayNumbers);
}
And then there are 2 implementations for this interface. One is BubbleSort
:
@Component
@Qualifier("Bubble")
public class BubbleSort implements SortAlgorithem {
Log log=LogFactory.getLog(BubbleSort.class);
public int[] sort(int[] numbers) {
log.info("Bubble sort is called");
return numbers;
}
}
and the other is QuickSort
:
@Component
@Qualifier("Quick")
//@Primary
public class QuickSort implements SortAlgorithem{
Log log= LogFactory.getLog(QuickSort.class);
public int[] sort(int[] numbers) {
log.info("Quick Sort is called");
return numbers;
}
}
At the end, when I call my app it complains with this message:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
I am wondering... Why @Qualifier
annotation does not work?
The solution to above problems is to use @Primary annotation. @Primary. This Indicates that a particular bean should be given preference when multiple beans are candidates to be autowired to a single-valued dependency. If exactly one 'primary' bean exists among the candidates, it will be the autowired value.
Spring @Primary annotation is used to give a higher preference to the marked bean when multiple beans of the same type exist. Spring, by default, auto-wires by type. And so, when Spring attempts to autowire and there are multiple beans of the same type, we'll get a NoUniqueBeanDefinitionException: Caused by: org.
Spring @Bean Annotation is applied on a method to specify that it returns a bean to be managed by Spring context. Spring Bean annotation is usually declared in Configuration classes methods. In this case, bean methods may reference other @Bean methods in the same class by calling them directly.
The @Qualifier("student") uniquely identifies this bean with the "student" string. We have another bean called Manager . This bean is also identified with the @Qualifier("manager") annotation. The CommandLineRunner interface indicates that a bean should run when it is contained within a SpringApplication .
You have annotated a field with @Autowired
and @Qualifier
, but you have also created a constructor which sets the field.
I think that Spring is using the constructor, but doesn't automatically know that the constructor parameter corresponds to the annotated field.
So move the annotations into the constructor declaration:
private SortAlgorithm sorter;
@Autowired
public BinarySearchImpl(@Qualifier("quick") SortAlgorithm sorter) {
this.sorter = sorter;
}
Alternatively, you could use a zero-arg constructor, keep your field annotation and let Spring inject using reflection. However in my opinion constructor-injection is better -- it allows you to unit test cleanly, without involving Spring or reflection.
As other answers point out, there are other ways to disambiguate autowired beans -- and the Spring docs explain them all -- but using qualifiers like this does work.
public interface SortAlgorithem {
public int[] sort(int[] arrayNumbers);
}
@Component("Bubble")
public class BubbleSort implements SortAlgorithem {
Log log = LogFactory.getLog(BubbleSort.class);
public int[] sort(int[] numbers) {
log.info("Bubble sort is called");
return numbers;
}
}
@Primary
@Component("Quick")
public class QuickSort implements SortAlgorithem {
Log log = LogFactory.getLog(QuickSort.class);
public int[] sort(int[] numbers) {
log.info("Quick Sort is called");
return numbers;
}
}
and then you need to use your implementations like this:
@Autowired
@Qualifier(value = "Bubble")
private SortAlgorithem bubbleSort;
@Autowired
@Qualifier(value = "Quick")
private SortAlgorithem quickSort;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With