Spring Boot启动报错:无法找到JwtProperties所需的String类型Bean
初始化Spring Boot应用时的JwtProperties注入错误
错误信息
Parameter 0 of constructor in com.aluguelsala.config.JwtProperties required a bean of type 'java.lang.String' that could not be found.
问题背景
已在application.yml中配置jwt相关参数,JwtProperties类添加了@Component和@ConfigurationProperties("jwt")注解,TokenService通过构造函数注入JwtProperties,但应用启动时触发上述错误。
配置与代码片段
application.yml配置
jwt: key: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa access-token-expiration: 3600000 refresh-token-expiration: 86400000
JwtProperties类
import org.springframework.boot.context.properties.ConfigurationProperties @ConfigurationProperties("jwt") data class JwtProperties( val key: String, val accessTokenExpiration: Long, val refreshTokenExpiration: Long, )
TokenService类
@Service class TokenService ( jwtProperties: JwtProperties ){ private val secretKey = Keys.hmacShaKeyFor( jwtProperties.key.toByteArray() ) fun generate( userDetails : UserDetails, expirationDate: Date, additionalClaims: Map<String, Any> = emptyMap() ):String = Jwts.builder() .claims() .subject(userDetails.username) .issuedAt(Date(System.currentTimeMillis())) .expiration(expirationDate) .add(additionalClaims) .and() .signWith(secretKey) .compact() fun isValid(token: String, userDetails: UserDetails): Boolean { val email = extractEmail(token) return userDetails.username == email && !isExpired(token) } fun extractEmail(token: String): String? = getAllClaims(token) .subject fun isExpired(token: String): Boolean = getAllClaims(token) .expiration .before(Date(System.currentTimeMillis())) private fun getAllClaims(token: String): Claims { val parser = Jwts.parser() .verifyWith(secretKey) .build() return parser .parseSignedClaims(token) .payload }
已尝试的解决步骤
- 确认JwtProperties与TokenService类在同一包或子包下
- 已给JwtProperties添加
@Component注解
解决方案
方案1:使用@ConstructorBinding+配置属性扫描
Kotlin data class结合@ConfigurationProperties时,需通过@ConstructorBinding明确告诉Spring用构造函数绑定配置值,同时在主应用类添加扫描注解:
修改JwtProperties类:
import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.boot.context.properties.ConstructorBinding @ConstructorBinding @ConfigurationProperties("jwt") data class JwtProperties( val key: String, val accessTokenExpiration: Long, val refreshTokenExpiration: Long, )
在主Spring Boot应用类添加扫描注解:
import org.springframework.boot.autoconfigure.SpringBootApplication import org.springframework.boot.context.properties.ConfigurationPropertiesScan import org.springframework.boot.runApplication @SpringBootApplication @ConfigurationPropertiesScan("com.aluguelsala.config") // 指定JwtProperties所在包路径 class AluguelSalaApplication fun main(args: Array<String>) { runApplication<AluguelSalaApplication>(*args) }
方案2:给data class参数添加默认值
允许Spring先创建实例,再通过配置覆盖默认值:
import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.stereotype.Component @Component @ConfigurationProperties("jwt") data class JwtProperties( val key: String = "", val accessTokenExpiration: Long = 0L, val refreshTokenExpiration: Long = 0L, )
方案3:将val改为var
让Spring通过setter方法绑定配置属性:
import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.stereotype.Component @Component @ConfigurationProperties("jwt") data class JwtProperties( var key: String = "", var accessTokenExpiration: Long = 0L, var refreshTokenExpiration: Long = 0L, )
原因说明
Spring Boot处理Kotlin data class的@ConfigurationProperties时,默认会将构造函数参数识别为需要注入的Bean,而非配置文件中的值。通过@ConstructorBinding可明确绑定逻辑;添加默认值或改为var则允许Spring先实例化,再通过反射/setter完成配置赋值。
内容的提问来源于stack exchange,提问作者Leonardo Lima
相关产品推荐
相关产品推荐

