Close

Spring - Java Generics as Autowiring Qualifiers

[Last Updated: Dec 5, 2020]

Spring 4.x is capable of using Java Generics types as an implicit qualification for dependency injection. Now we don't have to use @Qualifier or some specialized types to overcome this limitation in previous versions.

Consider List<String> and List<Integer>. They are of same type List but have different generics types, String and Integer. Spring first matches up the type and if the type has generics then matches up the generic type. If there is only one bean available (having same type and generics) for injection then performs injection otherwise throws error: NoUniqueBeanDefinitionException


Example

This example demonstrates that even though we have two instances of RateFormatter available for dependency injection, RateCalculator is still injected with the one matched by generic type.

package com.logicbig.example;

import java.math.BigDecimal;
import java.text.NumberFormat;

public class RateFormatter<T extends Number> {

  public String format(T number){
      NumberFormat format = NumberFormat.getInstance();
      if(number instanceof Integer){
          format.setMinimumIntegerDigits(0);
      }else if(number instanceof BigDecimal){
          format.setMinimumIntegerDigits(2);
          format.setMaximumFractionDigits(2);
      }//others

      return format.format(number);
  }
}
package com.logicbig.example;

import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;

public class RateCalculator {

  @Autowired
  private RateFormatter<BigDecimal> formatter;

  public void calculate() {
      BigDecimal rate = new BigDecimal(Math.random() * 100);
      System.out.println(formatter.format(rate));
  }
}

Defining beans and running the example

package com.logicbig.example;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.math.BigDecimal;

@Configuration
public class Config {

  @Bean
  RateFormatter<Integer> integerRateFormatter() {
      return new RateFormatter<Integer>();
  }

  @Bean
  RateFormatter<BigDecimal> bigDecimalRateFormatter() {
      return new RateFormatter<BigDecimal>();
  }

  @Bean
  RateCalculator rateCalculator() {
      return new RateCalculator();
  }

  public static void main(String[] args) {
      AnnotationConfigApplicationContext context =
              new AnnotationConfigApplicationContext(Config.class);
      RateCalculator bean = context.getBean(RateCalculator.class);
      bean.calculate();
  }
}

Output

77.8

Dependencies and Technologies Used:

  • Spring Context 4.2.3.RELEASE: Spring Context.
  • JDK 1.8
  • Maven 3.0.4

Spring - Java Generics as Autowiring Qualifiers Select All Download
  • generics-qualifier-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • Config.java

    See Also