You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin/SpringBoot中@PropertySource里@Value注入的问题

Kotlin Spring Boot中@PropertySource属性注入的正确实现方式

你当前写法出错的核心原因是:Spring不会对companion object中的属性执行@Value注入。伴生对象属于类的静态成员范畴,而Spring的依赖注入是基于实例对象的,因此你定义的lateinit属性永远不会被初始化,运行时必然抛出未初始化异常。

对应Java中通过getter/setter访问配置属性的实现,Kotlin中有两种常用方案:

方案一:基于实例的依赖注入(推荐)

这是符合Spring设计规范的标准写法,将配置类作为普通的Spring Bean,通过依赖注入获取实例后访问属性:

import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.PropertySource

@Configuration
@PropertySource("classpath:app-properties.properties")
class AppProperties {
    // 用lateinit var允许Spring后续注入
    @Value("\${app.storage.types}")
    lateinit var appStorageType: String

    @Value("\${app.device.supported-protocols}")
    lateinit var appDeviceSupportedProtocols: String

    // 也可以用val配合可空类型,Spring会通过反射直接赋值
    // @Value("\${app.storage.types}")
    // val appStorageType: String? = null
}

在需要使用配置的类中,通过构造函数注入AppProperties实例:

import org.springframework.stereotype.Service

@Service
class BusinessService(private val appProperties: AppProperties) {
    fun process() {
        val storageType = appProperties.appStorageType
        val protocols = appProperties.appDeviceSupportedProtocols
        // 业务逻辑处理
    }
}

方案二:模拟静态调用(不推荐)

如果确实需要类似Java静态调用的方式,可以通过@PostConstruct将实例引用注入到伴生对象中,但这种方式会引入全局状态,不利于测试和解耦:

import org.springframework.beans.factory.annotation.Value
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.PropertySource
import javax.annotation.PostConstruct

@Configuration
@PropertySource("classpath:app-properties.properties")
class AppProperties {
    @Value("\${app.storage.types}")
    lateinit var appStorageType: String

    @Value("\${app.device.supported-protocols}")
    lateinit var appDeviceSupportedProtocols: String

    companion object {
        lateinit var INSTANCE: AppProperties
    }

    @PostConstruct
    fun initInstance() {
        INSTANCE = this
    }
}

调用时直接通过伴生对象的实例引用访问属性:

val storageType = AppProperties.INSTANCE.appStorageType

注意:优先使用方案一,它遵循Spring的依赖注入原则,能保证代码的可测试性和可维护性;方案二仅用于特殊场景,需谨慎使用。

内容的提问来源于stack exchange,提问作者hell_storm2004

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 17:20:41