CDI 注入样式
CDI injection styles
我读到我可以通过 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 的原因,当它说它让 class 成为 immutable.
任何人都可以向我展示这些注入样式的有用示例吗?
第一个简短。任何特定的 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 世界中更受欢迎。
后一种情况很少见。要注入的具有可变字段的可变对象很奇怪,但它可能会派上用场。例如:
- 这样的注入有时用于有状态和 SessionScoped bean 来为其可写属性提供合理的默认值。
- 当对象需要进行单元测试并且有很多依赖项时也会使用这种情况(JSF backing beans 可能是一个原始的例子)。基于构造函数的 10 个 bean 注入可能最终会编写成吨的样板代码,而基于 setter 的注入可能是一种合理的折衷方案。
- 如果 POJO 没有合适的构造函数,针对托管环境的 POJO 适配可能会以基于 setter 的注入结束。
我读到我可以通过 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 的原因,当它说它让 class 成为 immutable.
任何人都可以向我展示这些注入样式的有用示例吗?
第一个简短。任何特定的 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 世界中更受欢迎。
后一种情况很少见。要注入的具有可变字段的可变对象很奇怪,但它可能会派上用场。例如:
- 这样的注入有时用于有状态和 SessionScoped bean 来为其可写属性提供合理的默认值。
- 当对象需要进行单元测试并且有很多依赖项时也会使用这种情况(JSF backing beans 可能是一个原始的例子)。基于构造函数的 10 个 bean 注入可能最终会编写成吨的样板代码,而基于 setter 的注入可能是一种合理的折衷方案。
- 如果 POJO 没有合适的构造函数,针对托管环境的 POJO 适配可能会以基于 setter 的注入结束。