【问题标题】:CDI injection stylesCDI 注入方式
【发布时间】:2016-04-13 09:53:31
【问题描述】:
我读到我可以通过 3 种不同的方式注入 bean:
-
作为字段
public class Checkout {
private @Inject ShoppingCart cart;
}
-
在 bean 构造函数中
public class Checkout {
private final ShoppingCart cart;
@Inject
public Checkout(ShoppingCart cart) {
this.cart = cart;
}
}
-
在初始化器中
public class Checkout {
private ShoppingCart cart;
@Inject
void setShoppingCart(ShoppingCart cart) {
this.cart = cart;
}
}
我一直使用第一种样式,我不知道何时以及为什么要使用其他两种样式。我找到了使用构造函数注入 here 的原因,当它说它让类不可变时。
谁能告诉我这些注入方式的有用示例?
【问题讨论】:
标签:
jakarta-ee
dependency-injection
cdi
【解决方案1】:
第一个简短而简单。任何特定的 CDI 驱动的应用程序都是一个例子。
当您使用类型与注入字段匹配的对象操作方法时,第二个会派上用场。一个例子是:
public class Garage {
private final Car expected;
private final List<Car> cars = new LinkedList<>();
@Inject
public Garage(@CarEtalon Car expected) {
this.expected = expected;
}
public void add(Collection<Car> toAdd) {
Car expectsCheck = null;
for (Iterator<Car> i = toAdd.iterator(); i.hasNext(); ) {
// Due to an autocomplete issue, you've made a typo...
expected = iterator.next();
// and your class could've been broken by a simple typo,
// but since our logical data model is reflected in code
// by using 'final' keyword, compiler will stop us here.
if (expected.matches(expectsCheck)) {
cars.add(expectsCheck);
}
}
}
}
这个例子是相当综合的,但它很好地反映了这个想法。 POJO 适配(带有 XML 描述符)可以利用这种实例化,因为基于构造函数的初始化在 SE 世界中更为流行。
后一种情况很少见。具有要注入的可变字段的可变对象有些奇怪,但它可能会派上用场。例如:
- 这种注入有时会用于 Stateful 和 SessionScoped bean,以便为其可写属性提供合理的默认值。
- 当需要对对象进行单元测试并且有很多依赖项时(JSF 支持 bean 可能是一个不切实际的例子),也会使用这种情况。基于构造函数的 10 个 bean 注入可能最终会编写大量样板代码,而基于 setter 的注入可能是一个合理的折衷方案。
- 如果 POJO 没有合适的构造函数,则对托管环境的 POJO 适配可能会以基于 setter 的注入方式结束。