Java 带CDI的受限泛型

Java 带CDI的受限泛型,java,generics,dependency-injection,cdi,Java,Generics,Dependency Injection,Cdi,JSR-299规范在§3.1中规定: 如果托管bean类是泛型类型,则它必须具有作用域 @依赖的。如果具有参数化bean类的托管bean声明 容器自动检测除@Dependent以外的任何作用域 并将其视为定义错误 实际上意味着你不能这样做: @Named @SessionScoped or @RequestScoped or similar public class MyProducer<T> {...} @Named @SessionScoped或@RequestScoped或类

JSR-299规范在§3.1中规定:

如果托管bean类是泛型类型,则它必须具有作用域 @依赖的。如果具有参数化bean类的托管bean声明 容器自动检测除@Dependent以外的任何作用域 并将其视为定义错误

实际上意味着你不能这样做:

@Named
@SessionScoped or @RequestScoped or similar
public class MyProducer<T> {...}
@Named
@SessionScoped或@RequestScoped或类似
公共类MyProducer{…}
做出这一决定的技术原因是什么

是否有可能在即将发布的CDI版本中进行补救

是否有处理/解决此问题的最佳实践

多谢各位


编辑-我经常使用的一种解决方法是将通用POJO bean注入到具有所需范围的bean中。通常,但并非总是如此。

所有非依赖作用域bean都必须被代理-AFAIK这在泛型类型中是不可能的

更新:

我很想能够更详细地解释这一点,但我不是;-)Weld使用,并且他们声明-尽管toplevel API不直接支持。但我们谈论的是规范,而不是焊接的实施


也许其他人可以填补这个空白?

这里有一个通用的、非依赖的bean类:

@ApplicationScoped
public class FavouriteChooser<T> {
    public T getFavourite() {
        // ...
    }
}
@ApplicationScoped
公共类收藏夹选择器{
公共T getfavorite(){
// ...
}
}
这个bean在应用程序中有多少个实例

以下是注射部位:

@Inject
private FavouriteChooser<String> favouriteWord;
@Inject
私人收藏夹选择器收藏夹单词;
还有一个:

@Inject
private FavouriteChooser<Integer> favouriteNumber;
@Inject
private FavouriteChooser<CharSequence> favouriteLetters;
@Inject
私人收藏夹选择器收藏夹编号;
您想更改您的答案吗?:D

哦,还有一个:

@Inject
private FavouriteChooser<Integer> favouriteNumber;
@Inject
private FavouriteChooser<CharSequence> favouriteLetters;
@Inject
私人收藏夹选择器收藏夹信件;
编辑。如果您想要一个解决方案,我建议将泛型类抽象化,并添加绑定该类型的具体子类。因此:

public abstract class MyProducer<T> {...}

@Named
@SessionScoped
public class MyStringProducer extends MyProducer<String> {}

@Named
@SessionScoped
public class MyIntegerProducer extends MyProducer<Integer> {}
公共抽象类MyProducer{…}
@命名
@会议范围
公共类MyStringProducer扩展了MyProducer{}
@命名
@会议范围
公共类MyIntegerProducer扩展MyProducer{}

这是样板,但每种类型只有三行。请记住,这将为每个类型的每个会话提供一个实例,这可能是您不想要的。

谢谢,jan。这已经说明了这一点-如果您也能解释为什么泛型类型不能被代理,那将是非常好的(我想这与java nemesis类型的主要擦除有关,但我不能对此指指点点).很好-所以只要你不把豆子命名,它就可以被注射?如果保留了作用域(是吗?——每个注入的FavoriteChooser应用程序的作用域都确定了吗?),那么唯一的限制就是我不能使用EL表达式访问它们?这与规范不矛盾吗?毕竟,它应该是一个托管bean。不,我的观点是,这段代码不可能工作!我已经声明了
FavoriteChooser
应用程序范围,这意味着只能有一个实例。但有两个注射部位不能满足同一对象的要求。我认为,这就是为什么不能将泛型类的实例注入到除dependent之外的任何作用域中的原因。很抱歉,在我写这个答案时,没有更清楚地说明我想说什么。我没来得及解释就匆匆忙忙地把它做完了:/。现在,我想到的一件事是一种新的作用域的概念,它是一种类型变量绑定作用域;如果您有一个范围是“where T is String”,那么在该范围内,您可以有一个
FavoriteChooser
的实例,它可以被注入到需要
FavoriteChooser
的任何地方。但这完全是理论上的想法!另外,还有一个简单但难看的解决方法,我已经添加了。顺便提一下,这个问题很好。我不知道这个限制,它真的让你思考。