Spring @Repository最佳实践
上下文:Web应用程序
我之前没有使用过Spring,但根据Spring文档,除非我们将它们声明为prototype
,否则所有bean都是singleton
。
- 不使用Spring:
通常我会在调用业务/服务层时实例化新的DAO。 如果它是RESTfull服务,我实例化几乎所有依赖于调用的对象。
- 随着spring:
我可以用@Repository
注释数据访问类,我也可以使用@Service
作为服务层类。
所以我的上面注释的类默认是singleton
。 有一个@Scope
注释,我们可以将它们声明为原型, 但似乎没有人这样做 。
- 没有Spring:
new Object();
每一次 - 随着spring:
singleton
我的问题是,
- 我之前使用的方式(每次创建新实例)不正确?
- 如果
@Repository
是singleton
,当没有这样的东西被解决时,它如何处理线程安全? (假设它由弹簧代理完成) - 什么是最佳实践,
@Repository
足够或添加@Scope('prototype')
会更好? - 我没有看到任何人将
@Scope('prototype')
与@Repository
(根据教程,博客等)。 有一个众所周知的原因吗? - 如果我的DAO类被多个大量高频率的线程访问怎么办? (这是我最关心的一个)
谢谢
你是对的 – 在spring的世界里,大部分豆子都是单身人士。
- 我之前使用的方式(每次创建新实例)不正确?
这是不正确的,因为它的工作原理。 它的问题是你在每个请求上实例化一个新的DAO实例 – 在某些情况下它可能很昂贵,而且无论如何它没有任何意义 – 为什么你需要一堆DAO实例? 另一方面,Spring不仅创建了一个单例,而且还将DAO注入服务或其他DAO等等,为你做了很多工作
- 如果@Repository是单例,当没有这样的东西被解决时,它如何处理线程安全? (假设它由弹簧代理完成)
在编写@Repository bean时,通常会在那里注入一个DataSource或一个EntityManager 。 DataSource.getConnection()方法应该是线程安全的。 关于EntityManager , Spring将注入一个代理,它对不同的线程表现不同,即不同的线程不会共享相同的JPA会话。
- 什么是最佳实践,@ Repository足够或添加@Scope(’prototype’)会更好?
最佳实践(或者更广泛的方法)是使用@Repository
- 我没有看到任何人将@Scope(’prototype’)与@Repository一起使用(根据教程,博客等)。 有一个众所周知的原因吗?
原因是创建多个@Repository bean实例没有任何好处
- 如果我的DAO类被多个大量高频率的线程访问怎么办? (这是我最关心的一个)
在这里,singleton比为每个请求创建一个新对象更好。 只是避免冗余同步,这样你的线程就不会在某些监视器上阻塞
-
不,但unit testing要困难得多,这就是dependency injection的全部内容。 通过在服务中注入DAO,您可以在测试期间通过注入模拟DAO轻松地对服务进行unit testing。 如果服务创建自己的DAO,那是不可能的。
-
除了在启动时初始化的线程安全实体管理器,会话工厂或JDBC模板之外,存储库通常是完全无状态的,因此并发调用不是问题:它是线程安全的。
-
存储库没有理由成为原型。 将原型DAO注入单件服务仍然会导致每个原型同时被调用。
-
没有理由这样做。
-
没问题:如果编码正确,它应该是线程安全的。
使用@Repository注释的组件应该是单例,因为它在整个生命周期中永远不会有多个/不同的状态。 是的,它可以容纳的唯一状态是连接对象,在创建对象期间只会设置一次。 它将包含与数据存储通信的逻辑/方法,每个方法将获取/返回所需的数据对象。 因此,不需要具有多个存储库实例。
Spring不会为您处理并发问题。 它并不意味着。 它所做的只是让你控制创建实例的数量,以便你的应用程序可以正常工作。
Singleton范围(显而易见)将只创建给定bean的一个实例并将其传递给所有依赖对象。
每个依赖对象的原型范围将创建自己的实例,而不是在其他对象之间共享。
对于DAO对象,您不太可能需要多个实例来与数据库通信。 所以单身人士总是被使用。