Europe: +41 78 715 83 09 - Asia: +84 ‎975 112 112
contact@finix.asia

Blog

30 Dec 2017

Kotlin Spring 5: Dependency Injection Part 2 (@Qualifer)

//
Comments0

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.

Kotlin Spring 5: Dependency Injection Part 3 (@Primary)

Leave a Reply

Translate »