使用之间有什么区别:
WeldContainer se = new Weld().initialize();
或
SeContainer se = SeContainerInitializer.newInstance().initialize();
我只想使用@Injection
和@Produce
批注,但是我没有发现这两种初始化对象实例的方式之间的区别。
上下文和依赖性注入(CDI)是一个规范。这意味着它仅定义API,不提供实现。这就是为什么必须包含诸如[[Weld之类的实现才能真正使用API的原因。 WeldContainer
类是特定于供应商的,而SeContainer
接口是规范的一部分。前者实现后者。
SeContainerInitializer
类是API的一部分,它将委托给应用程序附带的实现。因此,如果您使用Weld
作为实现,那么最终使用SeContainerInitializer
和SeContainer
与“在幕后”使用Weld
和WeldContainer
相同。从纯粹主义者的角度来看,最好仅依赖于规范的接口,而不要直接依赖于实现。这样,您便可以在需要时以及在需要时交换供应商,因为您使用的是所有实现的通用功能。但是,通常情况下,实现提供的功能要比规范要求的功能更多。为了使用该功能,您必须直接依赖于实现。换句话说,是否使用Weld
/ WeldContainer
或SeContainerInitialializer
/ SeContainer
取决于应用程序的(当前和将来)要求。如有疑问,请program to the interface。
请注意,API和实现之间的这种分离并非CDI独有。几乎整个
Java EE
-或众所周知的Jakarta EE-API都是这样工作的。一个示例是Java Persistence API(JPA)和Hibernate或EclipseLink(两个实现)。对于Java SE中的示例,有Java Database Connectivity(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()
方式。