WeldContainer 和 SeContainer
WeldContainer and SeContainer
使用有什么区别:
WeldContainer se = new Weld().initialize();
或
SeContainer se = SeContainerInitializer.newInstance().initialize();
我只想使用@Injection
和@Produce
注解,但是我没有发现这两种初始化对象实例的方式有什么区别。
上下文和依赖注入 (CDI) 是一个规范。这意味着它只定义了一个 API 并且不提供实现。这就是为什么您必须包含 Weld 等实现才能实际使用 API。 WeldContainer
class 是特定于供应商的,而 SeContainer
接口是规范的一部分。前者实现了后者。
SeContainerInitializer
class 是 API 的一部分,将委托给应用程序中包含的实现。因此,如果您使用 Weld 作为实现,那么最终使用 SeContainerInitializer
和 SeContainer
与使用 Weld
和 WeldContainer
相同 "under the hood".
从纯粹主义者的角度来看,最好只依赖规范的接口,永远不要直接依赖实现。这样您就可以在需要时更换供应商,因为您使用的是所有实现的通用功能。然而,通常实现提供的功能比规范要求的要多。为了使用该功能,您必须直接依赖于实现。
换句话说,您是使用Weld
/ WeldContainer
还是SeContainerInitialializer
/ SeContainer
取决于您的应用程序(当前和未来)的要求。如有疑问,program to the interface.
请注意,API 和实现之间的这种分离并不是 CDI 独有的。几乎整个 Java EE——或者现在已知的 Jakarta EE——API 都是这样工作的。一个例子是 Java Persistence API (JPA) 和 Hibernate 或 EclipseLink(两个实现)。例如 Java SE 中有 Java 数据库连接 (JDBC) API 和各种实现(即驱动程序)。
使用SeContainerInitializer
它将通过ServiceLoader.load(...)
加载一个实例并初始化它。
public static SeContainerInitializer newInstance() {
return findSeContainerInitializer();
}
private static SeContainerInitializer findSeContainerInitializer() {
SeContainerInitializer result;
Iterator<SeContainerInitializer> iterator = ServiceLoader.load(SeContainerInitializer.class, SeContainerInitializer.class.getClassLoader()).iterator();
if (!iterator.hasNext()) {
throw new IllegalStateException("No valid CDI implementation found");
}
try {
result = iterator.next();
} catch (ServiceConfigurationError e) {
throw new IllegalStateException("Error while instantiating SeContainerInitializer", e);
}
if (iterator.hasNext())
throw new IllegalStateException("Two or more CDI implementations found, only one is supported");
return result;
}
Weld 是 SeContainerInitializer
的一个实现,因此如果它存在于类路径中,SeContainerInitializer.newInstance()
方法将创建一个新的 Weld
实例并在此对象上调用 initialize()
方法。
一些提示这是一个不错的选择
SeContainerInitializer.newInstance()
是工厂方法。如果您想创建一个独立于供应商的应用程序,那会很好。但是Weld是CDI规范的参考实现。老实说,我认为没有必要选择其他实现方式。
new Weld().initialize()
将创建一个 WeldContainer
(这是 SeContainer
的一个实现)。使用此方法您将获得供应商锁定,但您可以使用许多有用的额外功能(例如,以编程方式添加替代项或拦截器)。
我的意见是:在这种情况下,供应商锁定无关紧要。
结论
如果您打算更改 CDI 实现,而不是 Weld,请使用独立的 SeContainerInitializer.newInstance()
,否则只需创建一个 Weld
实例。
如果我是你,我会使用 new Weld()
方式。
使用有什么区别:
WeldContainer se = new Weld().initialize();
或
SeContainer se = SeContainerInitializer.newInstance().initialize();
我只想使用@Injection
和@Produce
注解,但是我没有发现这两种初始化对象实例的方式有什么区别。
上下文和依赖注入 (CDI) 是一个规范。这意味着它只定义了一个 API 并且不提供实现。这就是为什么您必须包含 Weld 等实现才能实际使用 API。 WeldContainer
class 是特定于供应商的,而 SeContainer
接口是规范的一部分。前者实现了后者。
SeContainerInitializer
class 是 API 的一部分,将委托给应用程序中包含的实现。因此,如果您使用 Weld 作为实现,那么最终使用 SeContainerInitializer
和 SeContainer
与使用 Weld
和 WeldContainer
相同 "under the hood".
从纯粹主义者的角度来看,最好只依赖规范的接口,永远不要直接依赖实现。这样您就可以在需要时更换供应商,因为您使用的是所有实现的通用功能。然而,通常实现提供的功能比规范要求的要多。为了使用该功能,您必须直接依赖于实现。
换句话说,您是使用Weld
/ WeldContainer
还是SeContainerInitialializer
/ SeContainer
取决于您的应用程序(当前和未来)的要求。如有疑问,program to the interface.
请注意,API 和实现之间的这种分离并不是 CDI 独有的。几乎整个 Java EE——或者现在已知的 Jakarta EE——API 都是这样工作的。一个例子是 Java Persistence API (JPA) 和 Hibernate 或 EclipseLink(两个实现)。例如 Java SE 中有 Java 数据库连接 (JDBC) API 和各种实现(即驱动程序)。
使用SeContainerInitializer
它将通过ServiceLoader.load(...)
加载一个实例并初始化它。
public static SeContainerInitializer newInstance() {
return findSeContainerInitializer();
}
private static SeContainerInitializer findSeContainerInitializer() {
SeContainerInitializer result;
Iterator<SeContainerInitializer> iterator = ServiceLoader.load(SeContainerInitializer.class, SeContainerInitializer.class.getClassLoader()).iterator();
if (!iterator.hasNext()) {
throw new IllegalStateException("No valid CDI implementation found");
}
try {
result = iterator.next();
} catch (ServiceConfigurationError e) {
throw new IllegalStateException("Error while instantiating SeContainerInitializer", e);
}
if (iterator.hasNext())
throw new IllegalStateException("Two or more CDI implementations found, only one is supported");
return result;
}
Weld 是 SeContainerInitializer
的一个实现,因此如果它存在于类路径中,SeContainerInitializer.newInstance()
方法将创建一个新的 Weld
实例并在此对象上调用 initialize()
方法。
一些提示这是一个不错的选择
SeContainerInitializer.newInstance()
是工厂方法。如果您想创建一个独立于供应商的应用程序,那会很好。但是Weld是CDI规范的参考实现。老实说,我认为没有必要选择其他实现方式。
new Weld().initialize()
将创建一个 WeldContainer
(这是 SeContainer
的一个实现)。使用此方法您将获得供应商锁定,但您可以使用许多有用的额外功能(例如,以编程方式添加替代项或拦截器)。
我的意见是:在这种情况下,供应商锁定无关紧要。
结论
如果您打算更改 CDI 实现,而不是 Weld,请使用独立的 SeContainerInitializer.newInstance()
,否则只需创建一个 Weld
实例。
如果我是你,我会使用 new Weld()
方式。