Up until Spring 4 generics played no major role when it came to resolving injected bean dependencies. Suppose there are multiple beans of the same type implementing a generic interface. In a pre-Spring 4 world, any attempt to resolve such a bean by type would inevitably lead to a NonUniqueBeanDefinition exception, unless additional hints were provided (such as @Qualifier). Spring 4 removes this limitation by making generics a distinguishing part of a bean definition. Here is a short example.

Let’s say we have built a simple app allowing to transform Java objects into commonly used formats, such JSON or XML. Assume the transformation is carried by a feature called Printer which comes in two flavors a JsonPrinter and an XmlPrinter. The app provides access to the printer feature via a generic PrinterService:

public class PrinterService {

   private T printer;

   public PrinterService(T printer) {
     this.printer = printer;
   }

   public String print(E entity) {
     return printer.print(entity);
   }
}

Now we are left with declaring specific PrinterService beans allowing to print an object in a custom flavor:

@Configuration
@ComponentScan(basePackageClasses = PrinterService.class)
public class AppConfig {
   @Bean
   public PrinterService‹JsonPrinter› jsonService() {
     return new PrinterService‹JsonPrinter›(new JsonPrinter());
   }
   @Bean
   public PrinterService‹XmlPrinter› xmlService() {
     return new PrinterService‹XmlPrinter›(new XmlPrinter());
   }
}

Finally, let’s just use the declared beans. Provided you run on Spring 4 the following simple by-type autowiring will work like a charm:

@Autowired
private PrinterService‹JsonPrinter› jsonService;
@Autowired
private PrinterService‹XmlPrinter› xmlService;

Hope you appreciate the beauty of parametric polymorphism. Defining additional data types, such as JsonPrinterService or XmlPrinterService is ultimately not the way I’d want to go. As usual, feel free to download the source code and experiment on your own.

Source Code

Previous: Part 5 – @Component vs @Bean

Categories: JavaSpring

Tomas Zezula

Hello! I'm a technology enthusiast with a knack for solving problems and a passion for making complex concepts accessible. My journey spans across software development, project management, and technical writing. I specialise in transforming rough sketches of ideas to fully launched products, all the while breaking down complex processes into understandable language. I believe a well-designed software development process is key to driving business growth. My focus as a leader and technical writer aims to bridge the tech-business divide, ensuring that intricate concepts are available and understandable to all. As a consultant, I'm eager to bring my versatile skills and extensive experience to help businesses navigate their software integration needs. Whether you're seeking bespoke software solutions, well-coordinated product launches, or easily digestible tech content, I'm here to make it happen. Ready to turn your vision into reality? Let's connect and explore the possibilities together.