【发布时间】:2021-11-15 17:24:29
【问题描述】:
环境:Kotlin 1.5.30、SpringBoot 2.5.4(Spring 5.3.9)
背景与问题
我正在尝试创建一个组合注释来简化类似的模板注释代码。注解类是这样的:
@Profile("default") //NOTE 1: use a placeholder, see the investigations below
annotation class ProfileAware(
@get: AliasFor(annotation = Profile::class, attribute = "value")
val profiles: Array<String>,
//properties delegated for other annotations
)
预期用途:
@Component
@ProfileAware(profiles = ["dev"])
class TheBean {
init {
LoggerFactory.getLogger("TheBean").info("TheBean: I'm registered")
}
}
在 application.yaml 中:
spring:
profiles:
active: dev
但应用启动后,TheBean 并没有按预期注册。
调查与尝试
-
首先我在 github spring 存储库中搜索,发现:Regression: custom composed @Profile annotation without runtime retention no longer supported with component scanning。所以我尝试在@ProfileAware 上添加
@Retention(AnnotationRetention.RUNTIME),但没有效果。 -
试图从元注释中删除
("default")值(以及是否将默认值添加到profiles属性),但得到了java.lang.IllegalArgumentException: Must specify at least one profile。 -
试图从元注释中删除
@Profile("default"),但得到AnnotationConfigurationException: @AliasFor declaration on attribute 'profile' in annotation ... which is not meta-present. -
(重要)尝试直接在bean上使用@Profile(“dev”)而不是
ProfileAware,按预期工作。 -
(重要)尝试将元注释上的值更改为“dev”,它可以工作,但显然它是硬编码的,不符合我的需要。
是不是我做错了什么?或者是否可以使用动态 @Profile 值创建组合注释?
感谢您的阅读和帮助。
【问题讨论】:
-
您应该在
profile属性中指定默认值,而不是在注释上,当然保留确实需要为RUNTIME否则不会一起被检测到。 -
@M.Deinum 感谢您的评论,但是 1)在 Kotlin 中,运行时保留是 enabled by default,所以我们可以显式添加
RUNTIME但没关系。 2)我尝试在profilesattr 中添加默认值,但由于上述2个恼人的异常,仍然需要在@Profile注释中传递值。 -
哪个?正如您所说的 3 个错误...
@Profile也需要在那里但为空。可能是 Kotlin 正在扔东西,但它应该“正常工作(tm)”...... -
@M.Deinum 不,我相信它一定是弹簧错误而不是 Kotlin,因为
java.lang.IllegalArgumentException: Must specify at least one profile堆栈跟踪只是at org.springframework.core.env.ProfilesParser.parse(ProfilesParser.java:46) ~[spring-core-5.3.9.jar:5.3.9] -
这实际上让我想知道
@AliasFor在用作组合注释时是否支持@Profile。对于 Kotlin 部分,我想知道 Kotlin 是否删除/添加了一些内容,这使得阅读组合注释变得困难/不可能(因此提示 Kotlin)。
标签: spring spring-boot kotlin annotations