2016-04-12 8 views

ответ

-1

В этом Article объясняется хорошее объяснение концепций, написанных Адамом Биеном.

+1

Возможно я только один, но эта статья не была достаточно хороша для меня в объяснении разницы. – kukis

+0

Связанная статья даже не упоминает ни об аннотациях, о которых спрашивал ОП. –

0

Поскольку принятый ответ не решил мою проблему, я отправляю свой собственный ответ. Это не будет столь же хорошо, как статья Адам 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. Однако при замене ejb при импорте с inject вы получили бы NPE в классе ChampionsAPI при доступе к полю db - это потому, что ваш Singleton не был создан (по какой-то причине, может быть, потому, что нужно использовать интерфейсы при использовании javax.inject.Singleton?).

+1

Это не проблема пакета Singleton, а проблема обнаружения CDI. CDI не активируется в вашем случае. Если CDI правильно активирован (с использованием beans.xml и т. Д.), То инъекция будет работать правильно. – Rouliboy

3

Я нашел убедительное объяснение here:

По умолчанию javax.ejb.Singleton сессионных компонент являются транзакционными (раздел 13.3.7 в EJB 3.1 спецификации) и требую приобретения монопольной блокировки для каждого метод бизнеса вызова (разделов 4.8.5.4 и 4.8.5.5).

В отличие от этого 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); 
    } 
}