GUICE @Singleton 与默认作用域中的正确作用域处理



在(https://groups.google.com/forum/#!searchin/google-guice/Should$20Guice-Injected$20DAO$27s$20be$20Singletons$3F/google-guice/3B8XrwB-p18/B6OF13HWRnEJ(已经提出了类似的问题,但我认为它还没有收到令人满意的答案。

基线:我们在Tomcat上运行的JSF/Primefaces Web应用程序中使用Guice。持久性通过 JPA/Hibernate 处理。

现在我们所有的DAO(每个实体大约一个(都被注释为@Singleton。造成这种情况的唯一原因似乎是性能问题,因为应用程序的另一个(非 JSF 但 Web 服务(部分每秒将收到数千次点击,我们的主要开发人员认为,构建一次 DAO Singleton 然后以同步方式获取它比总是注入一个新实例(这是 Guice 默认范围(便宜。这与Google Guice Wiki关于Scopes的文章背道而驰:如果对象是无状态的并且创建成本低廉,则不需要范围。将绑定保留为无作用域,Guice 将根据需要创建新实例...尽管单例保存对象创建(以及后来的垃圾回收(,但单例的初始化需要同步;...

现在,在这种情况下,"单例初始化"到底是什么意思?初始化是否完成一次?每次注射?

假设是否正确,即在

上述情况下(每秒数千次点击(,使用@Singleton注释的 DAO 比使用默认范围更快、更好的资源明智?

由于我们将@Singleton用于我们的DAO,因此我们不会直接注入EntityManager,而是使用EntityManagerProvider,据我了解,这是正确的方式,因为提供程序被认为是线程安全的,这是@Singleton的要求。有没有一种"谷歌批准"的方法可以在你的Web应用程序中使用DAO包含Hibernate?

尽管单例保存了对象创建(以及后来的垃圾( 集合(,单例初始化需要同步; ...

现在,"单例初始化"到底是什么意思 上下文?初始化是否完成一次?每次注射?

这是单例作用域的实现(在 Guice 的发布版本中略有不同,但以下几点仍然成立(。 每次在任何位置注入单一实例范围的依赖项时,都将调用该提供程序上的 get() 方法来获取实例。

使用双重检查锁定,以便在首次创建单例后,将来对get()的调用很便宜:它们读取单个volatile字段并返回。

另一方面,使用 @Singleton DAO 意味着您必须通过每种方法中的Provider访问EntityManager,这涉及在某处ThreadLocalHashMap中查找EntityManager

结论:找到哪种选择对性能更好的唯一方法是对两者进行基准测试并选择更快的选项。 您可能会发现这两个选择都足够快,在这种情况下,您应该选择最干净的一个。

最新更新