CDI w.r.t 中的函数是特殊的吗? @Inject 与 BeanManager.getBeans(Function.class)?
Are Functions special in CDI w.r.t. @Inject vs BeanManager.getBeans(Function.class)?
我有两个 类,我想注入:
@ApplicationScoped
public class BeanThing {
public String apply(String s) {
return "bt(" + s + ")";
}
}
和
@ApplicationScoped
public class ClassFunction implements Function<String, String> {
@Override
public String apply(String s) {
return "cf(" + s + ")";
}
}
当我尝试在其他地方使用它们时,我得到不同的行为:
Set<Bean<?>> functions = beanManager.getBeans(Function.class);
for (Bean<?> untyped : functions) {
Bean<Function<String, String>> typed = (Bean<Function<String, String>>) untyped;
Function<String, String> function = beanManager.getContext(typed.getScope()).get(typed, beanManager.createCreationalContext(typed));
System.err.println(function.apply("beanManager"));
}
Set<Bean<?>> beanThings = beanManager.getBeans(BeanThing.class);
for (Bean<?> untyped : beanThings) {
Bean<BeanThing> typed = (Bean<BeanThing>) untyped;
BeanThing beanThing = beanManager.getContext(typed.getScope()).get(typed, beanManager.createCreationalContext(typed));
System.err.println(beanThing.apply("beanManager"));
}
System.err.println(injectedFunction.apply("injected"));
System.err.println(beanThing.apply("injected"));
System.err.println("injectedFunction is a function: " + (injectedFunction instanceof Function));
我的输出是:
bt(beanManager)
cf(injected)
bt(injected)
injectedFunction is a function: true
比我预期的少了一行。
有人能解释一下这是怎么回事吗?
解决方案,感谢 Siliarus 让我走上了正确的道路:
Set<Bean<?>> functions = beanManager.getBeans(new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[]{new WildcardType() {...}, new WildcardType() {...};
}
@Override
public Type getRawType() {
return Function.class;
}
});
如果我正确地得到了你的样本,你所缺少的是第一行 - 通过 BeanManager
.
获得时 Function
的输出
我猜 Set<Bean<?>> functions
是空的。原因是 泛型 。 Function
是一个通用类型,BeanManager
上的方法不太适合它。 CDI 规范很好地定义了 Typesafe resolution for parameterized types(尽管需要一些阅读)。
简而言之,您的 Function<String, String>
类型的 bean 将不能仅分配给您传递给 BeanManager
方法的原始 Function.class
。
附带说明一下,如果您希望即时实例化参数化类型,您始终可以使用 Instance<T>
, which supports the use of TypeLiteral
- 一种特殊结构,它不仅包含原始类型,还包含有关实际类型的信息参数.
我有两个 类,我想注入:
@ApplicationScoped
public class BeanThing {
public String apply(String s) {
return "bt(" + s + ")";
}
}
和
@ApplicationScoped
public class ClassFunction implements Function<String, String> {
@Override
public String apply(String s) {
return "cf(" + s + ")";
}
}
当我尝试在其他地方使用它们时,我得到不同的行为:
Set<Bean<?>> functions = beanManager.getBeans(Function.class);
for (Bean<?> untyped : functions) {
Bean<Function<String, String>> typed = (Bean<Function<String, String>>) untyped;
Function<String, String> function = beanManager.getContext(typed.getScope()).get(typed, beanManager.createCreationalContext(typed));
System.err.println(function.apply("beanManager"));
}
Set<Bean<?>> beanThings = beanManager.getBeans(BeanThing.class);
for (Bean<?> untyped : beanThings) {
Bean<BeanThing> typed = (Bean<BeanThing>) untyped;
BeanThing beanThing = beanManager.getContext(typed.getScope()).get(typed, beanManager.createCreationalContext(typed));
System.err.println(beanThing.apply("beanManager"));
}
System.err.println(injectedFunction.apply("injected"));
System.err.println(beanThing.apply("injected"));
System.err.println("injectedFunction is a function: " + (injectedFunction instanceof Function));
我的输出是:
bt(beanManager)
cf(injected)
bt(injected)
injectedFunction is a function: true
比我预期的少了一行。
有人能解释一下这是怎么回事吗?
解决方案,感谢 Siliarus 让我走上了正确的道路:
Set<Bean<?>> functions = beanManager.getBeans(new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[]{new WildcardType() {...}, new WildcardType() {...};
}
@Override
public Type getRawType() {
return Function.class;
}
});
如果我正确地得到了你的样本,你所缺少的是第一行 - 通过 BeanManager
.
Function
的输出
我猜 Set<Bean<?>> functions
是空的。原因是 泛型 。 Function
是一个通用类型,BeanManager
上的方法不太适合它。 CDI 规范很好地定义了 Typesafe resolution for parameterized types(尽管需要一些阅读)。
简而言之,您的 Function<String, String>
类型的 bean 将不能仅分配给您传递给 BeanManager
方法的原始 Function.class
。
附带说明一下,如果您希望即时实例化参数化类型,您始终可以使用 Instance<T>
, which supports the use of TypeLiteral
- 一种特殊结构,它不仅包含原始类型,还包含有关实际类型的信息参数.