2

使用有什么区别:

WeldContainer se = new Weld().initialize();

或者

SeContainer se = SeContainerInitializer.newInstance().initialize();

我只是想使用@Injection@Produce注解,但是我没有发现这两种初始化对象实例的方式的区别。

4

2 回答 2

6

上下文和依赖注入(CDI) 是一种规范。这意味着它只定义了一个 API,不提供实现。这就是为什么您必须包含诸如Weld之类的实现才能实际使用 API 的原因。该类WeldContainer是特定于供应商的,而SeContainer接口是规范的一部分。前者实现后者。

作为 API 一部分的SeContainerInitializer类将委托给应用程序中包含的实现。因此,如果您使用Weld作为实现,那么最终使用SeContainerInitializerandSeContainer与使用WeldWeldContainer“幕后”相同。

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

换句话说,是否使用Weld/WeldContainerSeContainerInitialializer/SeContainer取决于您的应用程序的(当前和未来)需求。如有疑问,请对界面进行编程

请注意,API 和实现之间的这种分离并不是 CDI 独有的。几乎整个Java EE(或者现在已知的Jakarta EE ) API 都以这种方式工作。Java Persistence API (JPA) 和HibernateEclipseLink(两种实现)就是一个例子。对于Java SE中的示例,有Java 数据库连接(JDBC) API 和各种实现(即驱动程序)。

于 2020-06-01T12:45:48.970 回答
1

使用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()方式。

于 2020-06-01T12:48:42.477 回答