web-dev-qa-db-ja.com

javax.inject.Singletonとjavax.ejb.Singletonの違い

少し混乱しています。 javax.inject.Singletonjavax.ejb.Singletonの正確な違いは何ですか?

24
Hakan Kiyar

もっともらしい説明を見つけました ここ

デフォルトでは、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);
    }
}
9
Jens Piegsa

受け入れられた答えは私の問題を解決しなかったので、私は自分の答えを投稿します。 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サービスに挿入されます。ただし、インポートのejbinjectに置き換えると、ChampionsAPIでNPEを受け取ります。 dbフィールドへのアクセス中のクラス-これは、シングルトンが作成されなかったためです(何らかの理由で、おそらくjavax.inject.Singleton?の使用中にインターフェイスを使用する必要があるため)。

1
kukis