通用 CDI 生产者方法未按预期工作
我有一个 CDI 生产者方法 - 根据与此示例无关的某些条件 - 创建不同类型的对象:
public class TestProducer {
@Produces @TestQualifier
public Object create(InjectionPoint ip) {
if(something) {
return "a String";
} else {
return Integer.valueOf(42);
}
}
但是在使用此生产者时,我总是在以下情况下收到错误:
@Named("test")
public class TestComponent {
...
@Inject public void setA(@TestQualifier String stringValue) {
...
@Inject public void setB(@TestQualifier Integer integerValue) {
它仅在生产者的 create 方法时有效方法签名中具有预期的类型:
public class TestProducer {
@Produces @SpringBean
public String create(InjectionPoint ip) {
现在字符串已正确注入,但我无法从生产者方法中生成整数。但这正是我想要避免的,因为生产者本身应该是完全通用的。
我做错了什么或者没有办法实现我想要的行为吗?
I have a CDI producer method which - depending on some conditions not relevant to this example - creates objects of different types:
public class TestProducer {
@Produces @TestQualifier
public Object create(InjectionPoint ip) {
if(something) {
return "a String";
} else {
return Integer.valueOf(42);
}
}
but when using this producer, I always get an error in the followin situation:
@Named("test")
public class TestComponent {
...
@Inject public void setA(@TestQualifier String stringValue) {
...
@Inject public void setB(@TestQualifier Integer integerValue) {
It only works when the create method of the producer has the expected type in the method signature:
public class TestProducer {
@Produces @SpringBean
public String create(InjectionPoint ip) {
Now the String get's injected correctly, but I have no way to also generate an integer from the producer method. But this is exactly what I want to avoid, since the producer itself should be completely generic.
Am I doing something wrong or is there no way to achieve the behaviour I want?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
所有 CDI 文档都清楚地表明 CDI 执行类型安全依赖注入 - 并且它是 CDI 的一个尊贵属性。恕我直言,您想要做的正是 CDI 试图避免的。您希望容器将
Object
转换为每种类型,而 CDI 无法以这种方式工作。注入点
stringValue
和integerValue
只能接收具有java.lang.String
和java.lang.Integer
的 bean code> 在其 bean 类型 分别。java.lang.Object
不满足此标准。我有两个建议。首先,由于您有两个或多个不同类型的注入点,因此请为该类型创建两个或多个生成器方法:
如果
something
条件只是检查注入点的类型(我的意思),那么它就可以工作。我打赌就是这样)。但是,如果
something
条件确实使用注入点类型之外的其他条件决定类型,我建议您自己做“肮脏的工作”:将返回值注入对象类型注入点并手动进行转换:
要点是,与其他一些 DI 框架不同,CDI 不能针对 Java 类型系统工作 - 相反,它大量使用它。不要试图对抗它,而是利用 CDI 的这一方面对你有利:)
All CDI documentation makes it clear that CDI does typesafe dependency injection - and it is an exalted property of CDI. IMHO, what you are trying to do is just what CDI tries to avoid. You want the container to cast
Object
to each type and CDI does not work that way.The injections points
stringValue
andintegerValue
can only receive a bean which hasjava.lang.String
andjava.lang.Integer
in its list of bean types respectively.java.lang.Object
does not satisfy this criterion.I have two suggestions. First, since you have two or more injection points of different types, create two or more producer methods for that types:
It works if the
something
condition is just to check the type of the injection point (what I am betting is the case).However, if the
something
condition does decide the type using other criteria than the type of the injection point, I'd suggestion to do the "dirty job" yourself: inject the returned value in anObject
-typed injection point and does the cast manually:The main point is that, unlike some other DI frameworks, CDI does not work against the Java type system - on the contrary, it heavily uses it. Do not try to fight against it but use this aspect of CDI in your favor :)
无论如何,
Object
的生产者很奇怪。我不确定这是否是规范所禁止的,或者这是一个错误,但我认为您可以采取一些巧妙的解决方法:然后注入
ValueHolder
和ValueHolder;
A producer for
Object
is strange anyway. I'm not sure if this is forbidden by the spec, or it's a bug, but I think you can make some clever workaround:And then inject a
ValueHolder<String>
andValueHolder<Integer>
它可以使用 CDI 创建通用对象,如下所示:
适用于焊接 2.2.0。
我认为这也适用于某些以前的版本。
Its possible create generic objects with CDI produces like that:
Works on weld 2.2.0.
I think that works on some previous versions as well.
您的初始化方法将查找具有 API 类型 String 和 Integer 的托管 bean,但您的生产者方法 bean 仅具有 API 类型(在生产者方法的情况下,返回类型)对象。
因此,您只能在初始化方法注入字段中使用 Object,然后区分接收者主体的 int 类型,或者简单地将它们和生产者方法包装在可以返回 Strings 或 Int 的实际类型中(但我会避免仿制药)
Your initializer methods will look for a managed bean with API types String and Integer, but your producer method bean only has API type (in case of producer method, return type) Object.
You can therefore only use Object in your initializer method injected fields and then discriminate between the types int the body of the receiver, or simply wrap them and the producer method in an actual type that can return Strings or Int (but I'd avoid the generics)