0

Lets say we have a Coach interface:

public interface Coach {
    public String getDailyWorkout();
}

And 2 different implementations for the Coach interface:

@Component
public class CricketCoach implements Coach{

    @Override
    public String getDailyWorkout() {
        return "Practice fast bowling for 15 minutes!!";
    }
}
@Component
public class BaseballCoach implements Coach{

    @Override
    public String getDailyWorkout() {
        return "Spend 30 minutes in batting practice";
    }
}

And my controller where use constructor injection in order to get the implementation from above. Let's say I want a BaseballCoach injected. In order to do so we can use the annotation @Qualifier like so:

@RestController
public class DemoController {
    private Coach myCoach;

    @Autowired
    public void DemoController(@Qualifier("baseballCoach")Coach myCoach) {
        this.myCoach = myCoach;
    }

    @GetMapping("/dailyworkout")
    public String getDailyWorkout() {
        return myCoach.getDailyWorkout();
    }
}

Why would we even use the qualifier if I could just use the "correct" class like so:

@RestController
public class DemoController {
    private Coach myCoach;

    @Autowired
    public void DemoController(BaseballCoach myCoach) {
        this.myCoach = myCoach;
    }

    @GetMapping("/dailyworkout")
    public String getDailyWorkout() {
        return myCoach.getDailyWorkout();
    }
}

Or even so the correct class in the variable "type"

@RestController
public class DemoController {
    private BaseballCoach myCoach;

    @Autowired
    public void DemoController(BaseballCoach myCoach) {
        this.myCoach = myCoach;
    }

    @GetMapping("/dailyworkout")
    public String getDailyWorkout() {
        return myCoach.getDailyWorkout();
    }
}

Are there any benefits to using the qualifier? Or is it just the recommended method to do so?

siggemannen
  • 3,884
  • 2
  • 6
  • 24
Pepe Peep
  • 15
  • 3
  • 1
    Related: [What does it mean to "program to an interface"?](https://stackoverflow.com/q/383947/6395627) – Slaw Mar 18 '23 at 00:26

1 Answers1

2

You can skip the @Qualifier and using an interface and use the BaseballCoach class in the constructor, but there is something called "Always code to interface"

Always code to interface means, the client code always holds an Interface object which is supplied by a factory.

Any instance returned by the factory would be of type Interface which any factory candidate class must have implemented. This way the client's application does not need to worry about implementation and the interface signature determines what all operations can be done.

This can be used to change the behavior of a program at runtime. It also helps you to write far better programs from the maintenance point of view.

Your code will work the same no matter if you use @Qualifier or directly inject the BaseballCoach but it is a matter of writing maintainable code that is easy to cover with tests.

https://medium.com/javarevisited/oop-good-practices-coding-to-the-interface-baea84fd60d3#

zawarudo
  • 1,907
  • 2
  • 10
  • 20
  • Thank you for the answer. So basically, by following the good practices of "always code for the interface" I am "obliged" to use Qualifiers right? – Pepe Peep Mar 19 '23 at 18:39
  • It is not that you are obligated, it just solves the issue that you will get if you had multiple classes using the same interface "No unique bean of type [com.pepe.Service] is defined: expected single matching bean but found 2: [serviceOne, serviceTwo]." It helps you to code to interface while not getting the exception from the above. – zawarudo Mar 19 '23 at 19:50