Consider marking one of the beans as @Primary
The correct approach:
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;
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.