им немного путать. Какая разница между javax.inject.Singleton
и javax.ejb.Singleton
?Разница между javax.inject.Singleton и javax.ejb.Singleton
ответ
В этом Article объясняется хорошее объяснение концепций, написанных Адамом Биеном.
Поскольку принятый ответ не решил мою проблему, я отправляю свой собственный ответ. Это не будет столь же хорошо, как статья Адам 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
?).
Это не проблема пакета Singleton, а проблема обнаружения CDI. CDI не активируется в вашем случае. Если CDI правильно активирован (с использованием beans.xml и т. Д.), То инъекция будет работать правильно. – Rouliboy
Я нашел убедительное объяснение 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);
}
}
Возможно я только один, но эта статья не была достаточно хороша для меня в объяснении разницы. – kukis
Связанная статья даже не упоминает ни об аннотациях, о которых спрашивал ОП. –