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

Blog

31 Dec 2017

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

//
Comments0

Kotlin Spring 5: Dependency Injection Part 2

Technologies used:   Kotlin 1.2.10 | Spring 5 | Maven 3.3.9 | Spring-boot 2.0.0.M7

In this third post, we will look into the @Primary annotation for Spring Dependency Injection

I will use the example given by Boraji on https://www.boraji.com/spring-4-qualifier-annotation-example

In Spring framework, the @Primary annotation is used to give higher preference to a bean, when there are multiple beans of same type.

The @Primary annotation may be used on any class directly or indirectly annotated with @Component or on methods annotated with @Bean.

The following examples demonstrate the use of the @Primary annotation.

Consider the following User interface.

package vn.finixasia.didemo.bean.user

interface User {
    fun doSomething()
}

Create two beans AdminUser and GuestUser

package vn.finixasia.didemo.bean.user

class AdminUser: User {
    override fun doSomething() {
        println("Inside doSomething() method of AdminUser")
    }
}

And

package vn.finixasia.didemo.bean.user

class GuestUser : User {
    override fun doSomething() {
        println("Inside doSomething() method of GuestUser")
    }
}

Declare the AdminUser and GuestUser beans in Kotlin Application Config

package vn.finixasia.didemo.config

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Primary
import vn.finixasia.didemo.bean.user.AdminUser
import vn.finixasia.didemo.bean.user.GuestUser
import vn.finixasia.didemo.bean.user.User

@Configuration
class AppConfig {

    val adminUser: User
        @Bean
        @Primary
        get() = AdminUser()

    val guestUser: User
        @Bean
        get() = GuestUser()
}

Now create a main application

package vn.finixasia.didemo

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import vn.finixasia.didemo.config.AppConfig
import vn.finixasia.didemo.bean.user.User

@SpringBootApplication
class DiDemoApplication

fun main(args: Array) {

 var actx = AnnotationConfigApplicationContext(AppConfig::class.java)
 var user = actx.getBean(User::class.java)
 user.doSomething()

 actx.close()
}

The Output

Inside doSomething() method of AdminUser

It is clear from the above output that the getAdminUser() method, annotated with @Primary, is autowired first.

The second example on how to use the @Primary annotation, it is when you have several Beans from the same type. If I use now our old example from the greeting as follow

With a GreetingService interface

package vn.finixasia.didemo.services

interface GreetingService {

    fun sayGreeting(): String
}

Two Service Implementations  GreetingServiceImpl and PrimaryGreetingService

package vn.finixasia.didemo.services

import org.springframework.stereotype.Service

@Service
class GreetingServiceImpl : GreetingService {
    private val HELLO_GURUS = "Hello !!!"

    override fun sayGreeting(): String {
        return HELLO_GURUS
    }
}

And

package vn.finixasia.didemo.services

import org.springframework.stereotype.Service

@Service
class PrimaryGreetingService : GreetingService {
    private val HELLO_GURUS = "Hello from Primary !!!"

    override fun sayGreeting(): String {
        return HELLO_GURUS
    }
}

With my Controller MyController

package vn.finixasia.didemo.controllers

import org.springframework.stereotype.Controller
import vn.finixasia.didemo.services.GreetingService

@Controller
class MyController constructor(var greetingService: GreetingService) {

    fun hello(): String {
        return greetingService.sayGreeting()
    }
}

From here Intelij tell me there is an error as he doesn’t know which GreetingService implementation to use, so if now we add @Primary annotation to our PrimaryGreetingService class

@Service
@Primary
class PrimaryGreetingService : GreetingService {

As you see the error disappear, and a launch from my main app

package vn.finixasia.didemo

import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.SpringBootApplication
import vn.finixasia.didemo.controllers.MyController

@SpringBootApplication
class DiDemoApplication

fun main(args: Array<String>) {
    var ctx = SpringApplication.run(DiDemoApplication::class.java, *args)
    var controller = ctx.getBean("myController") as MyController
    controller.hello()
    ctx.close()
}

The primary Greeting is call

Kotlin Spring 5: Dependency Injection Part 4 (@Profile)

Leave a Reply

Translate »