简体   繁体   中英

how to use spring annotations like @Autowired or @Value in kotlin for primitive types?

Autowiring a non-primitive with spring annotations like

@Autowired
lateinit var metaDataService: MetaDataService

works.

But this doesn't work:

@Value("\${cacheTimeSeconds}")
lateinit var cacheTimeSeconds: Int

with an error:

lateinit modifier is not allowed for primitive types.

How to autowire primitve properties into kotlin classes?

You can also use the @Value annotation within the constructor:

class Test(
    @Value("\${my.value}")
    private val myValue: Long
) {
        //...
  }

This has the benefit that your variable is final and none-nullable. I also prefer constructor injection. It can make testing easier.

@Value("\\${cacheTimeSeconds}") lateinit var cacheTimeSeconds: Int

should be

@Value("\${cacheTimeSeconds}")
val cacheTimeSeconds: Int? = null

I just used Number instead of Int like so...

    @Value("\${cacheTimeSeconds}")
    lateinit var cacheTimeSeconds: Number

The other options are to do what others mentioned before...

    @Value("\${cacheTimeSeconds}")
    var cacheTimeSeconds: Int? = null

Or you can simply provide a default value like...

    @Value("\${cacheTimeSeconds}")
    var cacheTimeSeconds: Int = 1

In my case I had to get a property that was a Boolean type which is primitive in Kotlin, so my code looks like this...

    @Value("\${myBoolProperty}")
    var myBoolProperty: Boolean = false

Try to set a default value

    @Value("\${a}")
    val a: Int = 0

in application.properties

a=1

in the code

package com.example.demo

import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.CommandLineRunner
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.stereotype.Component

@SpringBootApplication
class DemoApplication

fun main(args: Array<String>) {
    runApplication<DemoApplication>(*args)
}

@Component
class Main : CommandLineRunner {

    @Value("\${a}")
    val a: Int = 0

    override fun run(vararg args: String) {
        println(a)
    }
}

it will print 1

or use contructor inject

@Component
class Main(@Value("\${a}") val a: Int) : CommandLineRunner {

    override fun run(vararg args: String) {
        println(a)
    }
}

The problem is not the annotation, but the mix of primitive and lateinit , as per this question , Kotlin does not allow lateinit primitives.

The fix would be to change to a nullable type Int? , or to not use lateinit .

This TryItOnline shows the issue.

Kotlin compiles Int to int in java code. Spring wanted non-primitive types for injection, so you should use Int? / Boolean? / Long? and etc. Nullable types kotlin compile to Integer / Boolean / etc.

Without default value and outside constructor

From:

@Value("\${cacheTimeSeconds}") lateinit var cacheTimeSeconds: Int

To:

@delegate:Value("\${cacheTimeSeconds}")  var cacheTimeSeconds by Delegates.notNull<Int>()

Good Luck

Kotlin doesn't have primitive type

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM