java javax.inject.Singleton 和 javax.ejb.Singleton 的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36568344/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Difference between javax.inject.Singleton and javax.ejb.Singleton
提问by Hakan Kiyar
im little confused. What is the exact difference between javax.inject.Singleton
and javax.ejb.Singleton
?
我有点困惑。javax.inject.Singleton
和之间的确切区别是javax.ejb.Singleton
什么?
回答by Jens Piegsa
I found a plausible explanation here:
我在这里找到了一个合理的解释:
By default,
javax.ejb.Singleton
session beans are transactional (section 13.3.7 of the EJB 3.1 specification) and require acquisition of an exclusive lock for every business method invocation (sections 4.8.5.4 and 4.8.5.5).In contrast, a
javax.inject.Singleton
is not transactional and does not support container-managed concurrency (the major consequence being that no locking scheme is implemented by the container). [...]If you don't need EJB features, stick with
@ApplicationScoped
(javax.inject.Singleton
is not defined by CDI, and its semantics are therefore not governed by that specification).
默认情况下,
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 定义的,因此它的语义不受该规范的约束)。
To reduce future confusion, I use this small unit test (first level package name needs to be replaced):
为了减少以后的混淆,我使用了这个小单元测试(第一级包名需要替换):
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);
}
}
回答by kukis
Since accepted answer didn't solve my problem I post my own answer. It won't be as good as article by Adam Bien but definitely will be more practical:
由于接受的答案没有解决我的问题,我发布了我自己的答案。它不会像 Adam Bien 的文章那么好,但肯定会更实用:
Consider following code:
考虑以下代码:
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");
}
}
And this REST service:
这个 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();
}
}
Using javax.ejb.Singleton
this code works just fine. The DatabaseConnection
instance is created once and injected to REST service.
However when replacing ejb
in import with inject
you would receive NPE in ChampionsAPI class while accessing db field - that's because your Singleton was not created (for some reason, maybe because one need to make use of interfaces while using javax.inject.Singleton
? ).
使用javax.ejb.Singleton
此代码工作正常。该DatabaseConnection
实例创建一次并注入到 REST 服务中。但是,当ejb
使用导入替换时,inject
您会在访问 db 字段时在 ChampionsAPI 类中收到 NPE - 那是因为您的 Singleton 没有被创建(出于某种原因,可能是因为在使用时需要使用接口javax.inject.Singleton
?)。
回答by Christian Nwafor
In simple clarity:
简单明了:
javax.ejb.Singleton is an annotation used to create an @Singleton EJB (as opposed to @Sateless EJB or @Stateful EJB)
javax.ejb.Singleton 是用于创建@Singleton EJB(与@Sateless EJB 或@Stateful EJB 相对)的注解
On the other hand, javax.inject.Singleton is an annotation used to create a CDI with singleton scope
另一方面,javax.inject.Singleton 是一个注解,用于创建具有单例范围的 CDI
So basically, one creates a singleton EJB while the other creates a CDI with singleton scope
所以基本上,一个创建一个单例 EJB 而另一个创建一个具有单例范围的 CDI