Using Spring 5, I was puzzled as to how exactly the AnnotationConfigApplicationContext "magically" knows to use the correct implementation of my interface, since the references are to the interface not the implementing class.
Illustration
Note: Irrelevant code such as imports and unrelated behaviour has been ommitted
An interface CleaningTool and two implementing classes Broom and VacuumCleaner, with variations on the interface's method doCleanJob()
public interface CleaningTool {
void doCleanJob();
}
public class Broom implements CleaningTool {
@Override
public void doCleanJob() {
System.out.println("Sweep sweep sweep");
}
}
public class VacuumCleaner implements CleaningTool {
@Override
public void doCleanJob() {
System.out.println("Zoom zoom zoom");
}
}
Then, my AnnotationConfigApplicationContex uses my class AppConfig thusly:
@Configuration
public class AppConfig {
@Bean
public CleaningTool broom(){
return new Broom();
}
@Bean
public CleaningTool vacuum(){
return new VacuumCleaner();
}
}
Finally, in my MainApp class, where I invoke the AnnotationConfigApplicationContext's getBean() method, is where I tested this puzzling phenomenon which I, at first, expected not to work:
public class MainApp {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
CleaningTool vacuum = ctx.getBean(VacuumCleaner.class);
vacuum.doCleanJob();
}
}
Console output: Zoom zoom zoom
Even though my reference types in both my AppConfig and MainApp were CleaningTool, Spring somehow knew to seek out the Bean that matched the class VacuumCleaner.class, in such a way that the VacuumCleaner's behaviour was used.
How does this "magic" work?