Kotlin Spring 5: Dependency Injection Part 2 (@Qualifer)
Kotlin: Spring 5 Dependency Injection Part 1
Technologies used: Kotlin 1.2.10 | Spring 5 | Maven 3.3.9 | Spring-boot 2.0.0.M7
In this second post, we will look into the @Qualifier annotation for Spring Dependency Injection
I will use the example given by Boraji on https://www.boraji.com/spring-4-qualifier-annotation-example
The @Qualifier
is used to resolve the autowiring conflict when there are multiple beans of the same type.
The @Qualifier
annotation can be used on any class annotated with @Component
or on method annotated with @Bean
. This annotation can also be applied to constructor arguments or method parameters.
In this post, we will show you how the annotation@Qualifier
is used in the Spring application.
Consider the following Vehicle
interface.
package vn.finixasia.didemo.component interface Vehicle { fun start() fun stop() }
We create two beans call Car
package vn.finixasia.didemo.component import org.springframework.stereotype.Component @Component class Car : Vehicle { override fun start() { println("Car Started") } override fun stop() { println("Car Stopped") } }
And the Bike
package vn.finixasia.didemo.component import org.springframework.stereotype.Component @Component class Bike : Vehicle { override fun start() { println("Bike Started") } override fun stop() { println("Bike Stopped") } }
Create a VehicleService where the bean Vehicle will be injected by the constructor
package vn.finixasia.didemo.services import org.springframework.stereotype.Component import vn.finixasia.didemo.component.Vehicle @Component class VehicleService constructor(val vehicle: Vehicle) { fun service() { vehicle.start() vehicle.stop() } }
Now we create a QualiferApp and run it
@SpringBootApplication class DiDemoApplication fun main(args: Array<String>) { var ctx = SpringApplication.run(DiDemoApplication::class.java, *args) println(ctx.getBean(VehicleService::class.java).service()) }
we get the expected error
******************************************************APPLICATION FAILED TO START*************************** Description: Parameter 0 of constructor in vn.finixasia.didemo.services.VehicleService required a single bean, but 2 were found: - bike: defined in file [/Users/alex/Projects/learnSpring/di-demo/target/classes/vn/finixasia/didemo/bean/Bike.class] - car: defined in file [/Users/alex/Projects/learnSpring/di-demo/target/classes/vn/finixasia/didemo/bean/Car.class] Action: Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed Process finished with exit code 1
As you can see on the above result, there are two Beans detected Car and Bike, but only one is expected on the @Autowire of VehicleService. And so Spring throw a NoUniqueBeanDefinitionException
To fix the problem we will use the @Qualifer annotation.
We modify the Car as following
@Component @Qualifier("CarBean") class Car : Vehicle {
the Bike as following
@Component @Qualifier("BikeBean") class Bike : Vehicle {
And the VehicleService
@Component class VehicleService constructor(@Qualifier("CarBean") val vehicle: Vehicle) {
And now if we run again it works.