gpt4 book ai didi

spring - 如何在 SpEL 中按类型引用 bean?

转载 作者:行者123 更新时间:2023-12-04 16:27:42 28 4
gpt4 key购买 nike

以下是一个最小的示例,显示了我的问题。
Main.kt :

package com.mycompany.configurationpropertiestest

import org.slf4j.LoggerFactory
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.context.properties.ConstructorBinding
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.boot.runApplication
import org.springframework.scheduling.annotation.EnableScheduling
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Service


@SpringBootApplication
@EnableScheduling
@EnableConfigurationProperties(FooServiceConfig::class)
class Application

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


@ConstructorBinding
@ConfigurationProperties("configurationpropertiestest.foo")
data class FooServiceConfig(
val interval: Int = 1000,
val message: String = "hi"
)


@Service
class FooService(
private val myConfig: FooServiceConfig
) {
private val log = LoggerFactory.getLogger(this.javaClass)
//@Scheduled(fixedDelayString = "#{@FooServiceConfig.interval}")
//@Scheduled(fixedDelayString = "#{@myConfig.interval}")
@Scheduled(fixedDelayString = "\${configurationpropertiestest.foo.interval}")
fun talk() {
log.info(myConfig.message)
}
}

( @ConstructorBinding 用于允许 FooServiceConfig 的成员不可变。)
application.yml :
configurationpropertiestest:
foo:
interval: 500
message: "hi"
Test.kt :
package com.mycompany.configurationpropertiestest

import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.junit4.SpringRunner


@RunWith(SpringRunner::class)
@SpringBootTest
class Test {
@Test
fun `sit and wait`() {
Thread.sleep(3000)
}
}

它有效,但仅有效,因为我引用了 interval@Scheduled像这样注释:
@Scheduled(fixedDelayString = "\${configurationpropertiestest.foo.interval}")

这在某种程度上打破了我的服务很好的隔离配置。它突然必须了解外部事物,而现在它应该了解这些。

理想情况下,它只能通过 bean 的类型访问其配置:
@Scheduled(fixedDelayString = "#{@FooServiceConfig.interval}")

或通过注入(inject)的实例:
@Scheduled(fixedDelayString = "#{@myConfig.interval}")

但这些尝试导致 No bean named 'FooServiceConfig' availableNo bean named 'myConfig' available分别。

知道如何实现仅访问配置 bean 而不是全局配置值吗?

最佳答案

如果您不介意制作 FooService.myConfig公开,这应该有效:

@Service
class FooService(val myConfig: FooServiceConfig) {

val log = LoggerFactory.getLogger(this.javaClass)

@Scheduled(fixedDelayString = "#{@fooService.myConfig.interval}")
fun talk() {
log.info(myConfig.message)
}
}

更新:

显然 Spring 改变了用 @ConstructorBinding 注释的 bean 的名称。注释到 [configuration-properties-value]-[fully-qualified-bean-name] . FooServiceConfig最终成为 configurationpropertiestest.foo-com.mycompany.configurationpropertiestest.FooServiceConfig
因此,尽管很丑陋,但这也应该有效:
@Service
class FooService(private val myConfig: FooServiceConfig) {

val log = LoggerFactory.getLogger(this.javaClass)

@Scheduled(fixedDelayString = "#{@'configurationpropertiestest.foo-com.mycompany.configurationpropertiestest.FooServiceConfig'.interval}")
fun talk() {
log.info(myConfig.message)
}
}

最后,最后一个选项,回答标题问题:如何在 SpEL 中按类型引用 bean?您可以调用 beanFactory.getBean 来完成。 :
@Service
class FooService(private val myConfig: FooServiceConfig) {

val log = LoggerFactory.getLogger(this.javaClass)

@Scheduled(fixedDelayString = "#{beanFactory.getBean(T(com.mycompany.configurationpropertiestest.FooServiceConfig)).interval}")
fun talk() {
log.info(myConfig.message)
}
}

关于spring - 如何在 SpEL 中按类型引用 bean?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59771574/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com