javax.inject.Singleton和javax.ejb.Singleton之间的区别

Hak*_*yar 24 java singleton ejb inject java-ee-7

我很困惑.javax.inject.Singleton和之间的确切区别是javax.ejb.Singleton什么?

Jen*_*gsa 9

我在这里找到了一个似是而非的解释:

默认情况下,javax.ejb.Singleton会话bean是事务性的(EJB 3.1规范的第13.3.7节),并且需要为每个业务方法调用获取独占锁(第4.8.5.4节和第4.8.5.5节).

相反,a javax.inject.Singleton不是事务性的,并且不支持容器管理的并发(主要结果是容器没有实现锁定方案).[...]

如果您不需要EJB功能,请坚持使用@ApplicationScoped(javax.inject.Singleton不是由CDI定义,因此其语义不受该规范的约束).

为了减少将来的混淆,我使用这个小单元测试(需要替换第一级包名称):

import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;

import com.tngtech.archunit.core.domain.JavaClasses;
import com.tngtech.archunit.core.importer.ClassFileImporter;

import org.junit.Test;

public class SingletonTest {

    /** requires com.tngtech.archunit:archunit-junit:0.4.0 */
    @Test
    public void detectWrongSingletonAnnotation() {

        final ClassFileImporter importer = new ClassFileImporter();
        final JavaClasses classes = importer.importPackages("first_level_package");

        noClasses().should().beAnnotatedWith("javax.inject.Singleton")
                .as("Please use javax.ejb.Singleton instead of javax.inject.Singleton.")
                .check(classes);
    }
}
Run Code Online (Sandbox Code Playgroud)


kuk*_*kis 0

由于接受的答案没有解决我的问题,我发布了我自己的答案。它不会像 Adam Bien 的文章那么好,但肯定会更实用:

考虑以下代码:

import javax.annotation.PostConstruct;
import javax.ejb.Singleton;

@Singleton
public class DatabaseConnection {

    @PostConstruct
    public void init() {
        System.out.println("init");
    }

    public ChampionComp getFirstRecord() {
        return new ChampionComp("Ashe", "Teemo", "Warwick", 
                "Blitzcrank", "Syndra", "Anivia", "Brand", "Rammus", "Xin Zhao", "Irelia");
    }

}
Run Code Online (Sandbox Code Playgroud)

这个 REST 服务:

import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;

@Path("/champions")
public class ChampionsAPI {

    @Inject
    private DatabaseConnection db;

    @GET
    @Produces("text/plain")
    public String getClichedMessage() {
        ChampionComp comp = db.getFirstRecord();
        return comp.toString();
    }
}
Run Code Online (Sandbox Code Playgroud)

使用javax.ejb.Singleton这段代码效果很好。该DatabaseConnection实例创建一次并注入到 REST 服务。然而,当用ejb导入替换inject时,您将在访问 db 字段时在 ChampionsAPI 类中收到 NPE - 这是因为您的 Singleton 未创建(出于某种原因,可能是因为在使用时需要使用接口javax.inject.Singleton?)。

  • 这不是 Singleton 包的问题,​​而是 CDI 发现问题。在您的情况下,CDI 未“激活”。如果 CDI 被正确激活(使用 beans.xml 等),注入将正常工作。 (7认同)