受CDI限制的泛型

kos*_*tja 10 java generics dependency-injection cdi

JSR-299规范在§3.1中说明:

如果托管bean类是泛型类型,则它必须具有范围@Dependent.如果具有参数化bean类的托管bean声明除@Dependent之外的任何范围,则容器会自动检测问题并将其视为定义错误.

有效地意味着你不能这样做:

@Named
@SessionScoped or @RequestScoped or similar
public class MyProducer<T> {...}
Run Code Online (Sandbox Code Playgroud)

这个决定的技术原因是什么?

它是否会在即将发布的CDI版本中得到补救?

是否有处理/解决此问题的最佳做法?

谢谢

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

Tom*_*son 17

这是一个通用的非依赖bean类:

@ApplicationScoped
public class FavouriteChooser<T> {
    public T getFavourite() {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

应用程序中有多少个这样的bean实例?

这是一个注射部位:

@Inject
private FavouriteChooser<String> favouriteWord;
Run Code Online (Sandbox Code Playgroud)

这是另一个:

@Inject
private FavouriteChooser<Integer> favouriteNumber;
Run Code Online (Sandbox Code Playgroud)

你想改变你的答案吗?:d

哦,这是另一个:

@Inject
private FavouriteChooser<CharSequence> favouriteLetters;
Run Code Online (Sandbox Code Playgroud)

编辑.如果你想要一个解决方案,我建议你的泛型类是抽象的,并添加绑定类型的具体子类.所以:

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

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

@Named
@SessionScoped
public class MyIntegerProducer extends MyProducer<Integer> {}
Run Code Online (Sandbox Code Playgroud)

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

  • 不,我的观点是这段代码不可行!我已声明`FavouriteChooser`应用程序作用域,这意味着只能有一个实例.但它有两个注射部位,*不能被同一个物体*满足.而且,我认为,这就是为什么你不能在除依赖之外的任何范围内注入泛型类的实例. (3认同)