簡體   English   中英

javax.inject.Singleton 和 javax.ejb.Singleton 的區別

[英]Difference between javax.inject.Singleton and javax.ejb.Singleton

我有點困惑。 javax.inject.Singletonjavax.ejb.Singleton之間的確切區別是什么?

我在這里找到了一個合理的解釋:

默認情況下, javax.ejb.Singleton會話 bean 是事務性的(EJB 3.1 規范的第 13.3.7 節)並且需要為每個業務方法調用獲取排他鎖(第 4.8.5.4 和 4.8.5.5 節)。

相比之下, javax.inject.Singleton不是事務性的,不支持容器管理的並發(主要結果是容器沒有實現鎖定方案)。 [...]

如果您不需要 EJB 功能,請堅持使用@ApplicationScopedjavax.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);
    }
}

由於接受的答案沒有解決我的問題,我發布了我自己的答案。 它不會像 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");
    }

}

這個 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();
    }
}

使用javax.ejb.Singleton這段代碼工作得很好。 DatabaseConnection實例創建一次並注入到 REST 服務。 但是,當使用inject替換導入中的ejb ,您會在訪問 db 字段時在 ChampionsAPI 類中收到 NPE - 那是因為您的 Singleton 未創建(出於某種原因,可能是因為在使用javax.inject.Singleton需要使用接口?) .

簡單明了:

javax.ejb.Singleton 是用於創建@Singleton EJB(與@Sateless EJB 或@Stateful EJB 相對)的注解

另一方面,javax.inject.Singleton 是一個注解,用於創建具有單例范圍的 CDI

所以基本上,一個創建一個單例 EJB 而另一個創建一個具有單例范圍的 CDI

的概念很好地解釋背后在此給出的文章被亞當邊。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM