如何解决 @ConfigProperties 注解与 @Vetoed 注解的冲突问题?
2024-06-11 17:36:26
@ConfigProperties 与 @Vetoed 注解的冲突及其解决方案
问题
如果你试图将标注有 @ConfigProperties
注解的 MyConfig
类注入到标注有 @Vetoed
注解的 MyClass
类中,构建过程可能会失败并出现以下错误消息:
...
Caused by: jakarta.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type mycompany.thing.logging.MyConfig and qualifiers [@Default]
- injection target: parameter 'cfg' of mycompany.thing.logging.MyClass constructor
- declared on CLASS bean [types=[mycompany.thing.logging.MyClass, java.lang.Object], qualifiers=[@Default, @Any], target=mycompany.thing.logging.MyClass]
The following classes match by type, but have been skipped during discovery:
- mycompany.thing.logging.MyConfig was annotated with @Vetoed
解决方法
解决方法是移除 @ConfigProperties
注解,并在 MyConfig
类的每个字段上指定 prefix
参数。修改后的 MyConfig
类如下:
@Dependent
public class MyConfig {
@ConfigProperty(name = "mycompany.thing.logs.sizeLimit", defaultValue = "5G")
ByteAmount sizeLimit;
@ConfigProperty(name = "mycompany.thing.logs.useVDisk", defaultValue = "false")
boolean useVdisk;
@ConfigProperty(name = "mycompany.thing.logs.workerInterval", defaultValue = "PT0.1S")
Duration workerInterval;
@ConfigProperty(name = "mycompany.thing.logs.maintenanceInterval", defaultValue = "PT15M")
Duration maintenanceInterval;
// getters
}
原理
@Vetoed
注解指示 CDI 容器忽略带有该注解的类。当 MyConfig
类被标注有 @Vetoed
注解时,即使它带有 @ConfigProperties
注解,CDI 容器也不会将其识别为配置 bean。因此,MyClass
类无法通过依赖注入获取 MyConfig
实例。
移除 @ConfigProperties
注解并手动在每个字段上指定 prefix
参数,可以使 MyConfig
类仍能从配置中获取值,而无需 CDI 容器将其识别为配置 bean。
常见问题解答
1. 为什么 @Vetoed
注解会影响 @ConfigProperties
注解?
@Vetoed
注解会告诉 CDI 容器忽略带有该注解的类。当 MyConfig
类被标注有 @Vetoed
注解时,CDI 容器就会忽略它,即使它带有 @ConfigProperties
注解,也不会将其识别为配置 bean。
2. 除了移除 @ConfigProperties
注解之外,还有其他解决方法吗?
没有其他解决方法。移除 @ConfigProperties
注解并手动在每个字段上指定 prefix
参数是唯一可行的解决方案。
3. 为什么在每个字段上指定 prefix
参数是必要的?
在每个字段上指定 prefix
参数可以确保 MyConfig
类仍能从配置中获取值。如果不指定 prefix
参数,CDI 容器将无法识别 MyConfig
类中的字段,并且无法将其与配置属性关联。
4. 使用 @ConfigProperties
注解和手动指定 prefix
参数有什么区别?
使用 @ConfigProperties
注解可以自动将相关属性聚合到一个 CDI bean 中。手动指定 prefix
参数需要在每个字段上显式指定属性前缀,但它提供了更大的灵活性,因为它允许你对每个字段使用不同的前缀。
5. 如何在实践中使用此解决方法?
在实践中,你可以按照以下步骤使用此解决方法:
- 从
MyConfig
类中移除@ConfigProperties
注解。 - 在
MyConfig
类的每个字段上添加@ConfigProperty
注解,并指定适当的prefix
参数。 - 在
MyClass
类中,继续使用@Inject
注释注入MyConfig
实例。
通过遵循这些步骤,你可以解决 @ConfigProperties
注解和 @Vetoed
注解同时使用时的 Bean 否决问题。