Categories
Spring Spring Core

Generics as Auto-wiring Qualifiers

When we are using more than one implementation for a Type, we use @Qualifier annotation as explained in this article. We don’t want to use @Qualifier annotation when using Generics as shown in the below example.

Step 1 : Create Maven project and name it as GenericsAsQualifiers and copy below dependencies in pom.xml file.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>GenericsAsQualifiers</groupId>
  <artifactId>GenericsAsQualifiers</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>Geek Coders</name>
  <build>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.0</version>
        <configuration>
          <source>1.8</source>
          <target>1.8</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>5.2.6.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>5.2.6.RELEASE</version>
		</dependency>
	</dependencies>
</project>
Step 2 : Create a Generic Interface named University as below.
package net.geekcoders.example;

public interface University<T> {
	T totalAttendance();
}
Step 3 : Implement the Interface in StaffService class
package net.geekcoders.example;

import org.springframework.stereotype.Service;

@Service
public class StaffService implements University<Staff> {

	@Override
	public Staff totalAttendance() {
		// Business Logic goes here
		System.out.println("Execution of StaffService :: Staff attendance");
		return new Staff();
	}

}
  • Implemented the University generic interface here with Staff object as a Generic variable
Step 4 : Implement the Interface in StudentService class
package net.geekcoders.example;

import org.springframework.stereotype.Service;

@Service
public class StudentService implements University<Student> {

	@Override
	public Student totalAttendance() {
		// Business logic goes here
		System.out.println("Execution of Student service :: Student attendance");
		return new Student();
	}

}
  • Implemented the University generic interface here with Student object as a Generic variable.
Step 5 : Create Staff Pojo class
package net.geekcoders.example;

public class Staff {
	private String name;
	private String empNumber;
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}
	/**
	 * @return the empNumber
	 */
	public String getEmpNumber() {
		return empNumber;
	}
	/**
	 * @param empNumber the empNumber to set
	 */
	public void setEmpNumber(String empNumber) {
		this.empNumber = empNumber;
	}
}
Step 6 : Create a Student Pojo class
package net.geekcoders.example;

public class Student {
	private String name;
	private String regNumber;
	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}
	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}
	/**
	 * @return the regNumber
	 */
	public String getRegNumber() {
		return regNumber;
	}
	/**
	 * @param regNumber the regNumber to set
	 */
	public void setRegNumber(String regNumber) {
		this.regNumber = regNumber;
	}
}
Step 7 : Create UniversityController as below
package net.geekcoders.example;

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

@Controller
public class UniversityController {
	@Autowired
	private University<Student> studentAttendance;
	@Autowired
	private University<Staff> staffAttendance;
	
	public void getAllAttendance() {
		this.getStaffAttendance().totalAttendance();
		this.getStudentAttendance().totalAttendance();
	}
	/**
	 * @return the studentAttendance
	 */
	public University<Student> getStudentAttendance() {
		return studentAttendance;
	}
	/**
	 * @param studentAttendance the studentAttendance to set
	 */
	public void setStudentAttendance(University<Student> studentAttendance) {
		this.studentAttendance = studentAttendance;
	}
	/**
	 * @return the staffAttendance
	 */
	public University<Staff> getStaffAttendance() {
		return staffAttendance;
	}
	/**
	 * @param staffAttendance the staffAttendance to set
	 */
	public void setStaffAttendance(University<Staff> staffAttendance) {
		this.staffAttendance = staffAttendance;
	}
}
  • If you note the highlighted lines, we are using only @Autowiring annotation for both the fields of type University.
  • The difference is the Generics used in those types.
  • The IoC Container will look at the generics used and resolve the dependencies without any issues.
Step 8 : Create a Starter class as below to execute the example application we developed
package net.geekcoders.example;

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

@Configuration
@ComponentScan(basePackages = "net.geekcoders.example")
public class AppConfig {
	public static void main(String args[]) {
		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
		applicationContext.register(AppConfig.class);
		applicationContext.refresh();

		UniversityController controller = applicationContext.getBean(UniversityController.class);
		controller.getAllAttendance();
	}
}
  • We are invoking the getAllAttendance() method from UniversityController Bean.
  • I’m using only UniversityController.class as a parameter in getBean method instead of using getBean(“universityController”,UniversityController.java); because, i have not explicitly mentioned the Controller name as @Controller(“universityController”) while defining the UniversityController bean. 

The final structure of your project will look like below.

Execute this project from AppConfig.java class as a Java Application. You can see the output as below in your console.

That’s all for now on a very simple example of Generics as Autowiring Qualifiers…

Happy Reading!!!

Leave a Reply

Your email address will not be published. Required fields are marked *