Spring Boot 中基于表达式的自动装配(使用 Kotlin)
Expression based Autowire in Spring Boot (with Kotlin)
情况
我正在尝试提出一种方法来有条件地加载一个 bean(基于 2 属性 或环境变量的存在),如果它们丢失则加载另一个 bean。
变量
所以两个 属性(或环境变量)是:
ProtocolHOST
ProtocolPORT
因此,例如 java -jar xxxx -DProtocolHost=myMachine -DProtocolPort=3333
会使用我想要的 bean,但如果两者都缺失,那么您将获得另一个 bean。
@Component("Protocol Enabled")
class YesBean : ProtocolService {}
@Component("Protocol Disabled")
class NoBean : ProtocolService {
稍后在我的控制器中我有一个:
@Autowired
private lateinit var sdi : ProtocolService
所以我查看了多种选择:
同时使用 @ConditionalOnProperty
和 @ConditionalOnExpression
,我似乎无法取得任何进展。
我很确定我需要走 Expression 路线,所以我写了一些似乎失败的测试代码:
@PostConstruct
fun customInit() {
val sp = SpelExpressionParser()
val e1 = sp.parseExpression("'${ProtocolHost}'")
println("${e1.valueType} ${e1.value}")
println(System.getProperty("ProtocolHost")
}
哪个returns:
class java.lang.String ${ProtocolHost}
taco
所以我不确定我的 SPeL 解析是否正常工作,因为它看起来只是返回字符串“${ProtocolHost}”而不是处理正确的值。我假设这就是为什么我在表达式语言中所做的所有尝试都失败了 - 因此我被卡住了。
如有任何帮助,我们将不胜感激!
谢谢
更新
我确实通过执行以下操作使事情正常进行
我的主要是:
val protocolPort: String? = System.getProperty("ProtocolPort", System.getenv("ProtocolPort"))
val protocolHost: String? = System.getProperty("ProtocolHost", System.getenv("ProtocolHost"))
System.setProperty("use.protocol", (protocolHost != null && protocolPort != null).toString())
runApplication<SddfBridgeApplication>(*args)
然后是 bean 定义:
@ConditionalOnProperty(prefix = "use", name = arrayOf("protocol"), havingValue = "false", matchIfMissing = false)
@ConditionalOnProperty(prefix = "use", name = arrayOf("protocol"), havingValue = "false", matchIfMissing = false)
然而,这感觉像是一个 hack,我希望它可以直接在 SpEL 中完成,而不是提前预先设置变量。
这听起来像是基于 Java 的 bean 配置的完美用例:
@Configuration
class DemoConfiguration {
@Bean
fun createProtocolService(): ProtocolService {
val protocolPort: String? = System.getProperty("ProtocolPort", System.getenv("ProtocolPort"))
val protocolHost: String? = System.getProperty("ProtocolHost", System.getenv("ProtocolHost"))
return if(!protocolHost.isNullOrEmpty() && !protocolPort.isNullOrEmpty()) {
YesBean()
} else {
NoBean()
}
}
}
open class ProtocolService
class YesBean : ProtocolService()
class NoBean : ProtocolService()
您可能还想查看 Externalized Configurations 以替换 System.getProperty()
和 System.getenv()
。
这看起来像这样:
@Configuration
class DemoConfiguration {
@Bean
fun createProtocolService(@Value("${protocol.port:0}") protocolPort: Int,
@Value("${protocol.host:none}") protocolHost: String): ProtocolService {
return if (protocolHost != "none" && protocolPort != 0) {
YesBean()
} else {
NoBean()
}
}
}
情况
我正在尝试提出一种方法来有条件地加载一个 bean(基于 2 属性 或环境变量的存在),如果它们丢失则加载另一个 bean。
变量
所以两个 属性(或环境变量)是:
ProtocolHOST
ProtocolPORT
因此,例如 java -jar xxxx -DProtocolHost=myMachine -DProtocolPort=3333
会使用我想要的 bean,但如果两者都缺失,那么您将获得另一个 bean。
@Component("Protocol Enabled")
class YesBean : ProtocolService {}
@Component("Protocol Disabled")
class NoBean : ProtocolService {
稍后在我的控制器中我有一个:
@Autowired
private lateinit var sdi : ProtocolService
所以我查看了多种选择:
同时使用 @ConditionalOnProperty
和 @ConditionalOnExpression
,我似乎无法取得任何进展。
我很确定我需要走 Expression 路线,所以我写了一些似乎失败的测试代码:
@PostConstruct
fun customInit() {
val sp = SpelExpressionParser()
val e1 = sp.parseExpression("'${ProtocolHost}'")
println("${e1.valueType} ${e1.value}")
println(System.getProperty("ProtocolHost")
}
哪个returns:
class java.lang.String ${ProtocolHost} taco
所以我不确定我的 SPeL 解析是否正常工作,因为它看起来只是返回字符串“${ProtocolHost}”而不是处理正确的值。我假设这就是为什么我在表达式语言中所做的所有尝试都失败了 - 因此我被卡住了。
如有任何帮助,我们将不胜感激!
谢谢
更新
我确实通过执行以下操作使事情正常进行
我的主要是:
val protocolPort: String? = System.getProperty("ProtocolPort", System.getenv("ProtocolPort"))
val protocolHost: String? = System.getProperty("ProtocolHost", System.getenv("ProtocolHost"))
System.setProperty("use.protocol", (protocolHost != null && protocolPort != null).toString())
runApplication<SddfBridgeApplication>(*args)
然后是 bean 定义:
@ConditionalOnProperty(prefix = "use", name = arrayOf("protocol"), havingValue = "false", matchIfMissing = false)
@ConditionalOnProperty(prefix = "use", name = arrayOf("protocol"), havingValue = "false", matchIfMissing = false)
然而,这感觉像是一个 hack,我希望它可以直接在 SpEL 中完成,而不是提前预先设置变量。
这听起来像是基于 Java 的 bean 配置的完美用例:
@Configuration
class DemoConfiguration {
@Bean
fun createProtocolService(): ProtocolService {
val protocolPort: String? = System.getProperty("ProtocolPort", System.getenv("ProtocolPort"))
val protocolHost: String? = System.getProperty("ProtocolHost", System.getenv("ProtocolHost"))
return if(!protocolHost.isNullOrEmpty() && !protocolPort.isNullOrEmpty()) {
YesBean()
} else {
NoBean()
}
}
}
open class ProtocolService
class YesBean : ProtocolService()
class NoBean : ProtocolService()
您可能还想查看 Externalized Configurations 以替换 System.getProperty()
和 System.getenv()
。
这看起来像这样:
@Configuration
class DemoConfiguration {
@Bean
fun createProtocolService(@Value("${protocol.port:0}") protocolPort: Int,
@Value("${protocol.host:none}") protocolHost: String): ProtocolService {
return if (protocolHost != "none" && protocolPort != 0) {
YesBean()
} else {
NoBean()
}
}
}