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 作为实现,那么最终使用 SeContainerInitializerSeContainer 与使用 WeldWeldContainer 相同 "under the hood".

从纯粹主义者的角度来看,最好只依赖规范的接口,永远不要直接依赖实现。这样您就可以在需要时更换供应商,因为您使用的是所有实现的通用功能。然而,通常实现提供的功能比规范要求的要多。为了使用该功能,您必须直接依赖于实现。

换句话说,您是使用Weld / WeldContainer 还是SeContainerInitialializer / SeContainer 取决于您的应用程序(当前和未来)的要求。如有疑问,program to the interface.

请注意,API 和实现之间的这种分离并不是 CDI 独有的。几乎整个 Java EE——或者现在已知的 Jakarta EE——API 都是这样工作的。一个例子是 Java Persistence API (JPA) 和 HibernateEclipseLink(两个实现)。例如 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() 方式。