Spring @Repository 最佳实践
Spring @Repository best practices
上下文:Web 应用程序
我以前没用过Spring,但根据Spring文档,所有bean都是singleton
,除非我们将它们声明为prototype
。
- 不使用 Spring:
通常我会在调用 business/service 层时实例化新的 DAO。
如果它是一个 RESTfull 服务,我实例化几乎所有依赖调用的对象。
- 与Spring:
我可以使用 @Repository
注释数据访问 classes 并且我可以将 @Service
用于服务层 classes.
所以我的带有上述注释的 classes 默认是 singleton
。
有一个 @Scope
注释,我们可以将它们声明为原型,但似乎没有人这样做。
- 没有Spring:每次
new Object();
- 与Spring:
singleton
我的问题是,
- 我之前使用的方式(每次创建新实例)不正确?
- 如果
@Repository
是 singleton
,当没有这样的事情时,它如何处理线程安全? (假设它是由 spring 个代理完成的)
- 最佳做法是什么,
@Repository
就够了还是加 @Scope('prototype')
会更好?
- 我没看到有人将
@Scope('prototype')
与 @Repository
一起使用(根据教程、博客等)。有什么众所周知的原因吗?
- 如果我的 DAO class 被多个大量线程以非常高的频率访问怎么办? (这是我最关心的)
谢谢
不,但是单元测试要难得多,这就是依赖注入的全部意义所在。通过在服务中注入 DAO,您可以通过在测试期间注入模拟 DAO 轻松地对服务进行单元测试。如果服务创建自己的 DAO,那是不可能的。
存储库通常是完全无状态的,除了线程安全的实体管理器、会话工厂或 JDBC 在启动时初始化的模板,因此并发调用不是问题:它是线程-安全。
存储库没有理由成为原型。将原型 DAO 注入到单例服务中仍然会导致每个原型无论如何都被并发调用。
没有理由去做。
没问题:如果编码正确,它应该是线程安全的。
Spring 不会为您处理并发问题。这不是故意的。它所做的只是让您控制创建实例的数量,以便您的应用程序可以正常工作。
单例作用域(很明显)将只创建给定 bean 的一个实例并将其传递给所有相关对象。
每个依赖对象的原型范围将创建自己的实例,不在其他对象之间共享。
对于 DAO 对象,您不太可能需要多个实例来与数据库通信。所以单例经常被使用。
你是对的 - 在 Spring 世界中大多数 bean 都是单例。
- The way I used before (creating new instance each time) is incorrect ?
没有错,因为它有效。它的问题是你在每个请求上实例化一个新的 DAO 实例——在某些情况下它可能很昂贵,而且无论如何它没有任何意义——你为什么需要一堆 DAO 实例?
另一方面,Spring 不仅创建单例,而且将 DAO 注入服务或其他 DAO e.t.c。即为您做了很多工作
- If @Repository is singleton, how does it handle thread safety when there is no such a thing addressed? (Assume it is done by spring proxies)
当您编写@Repository bean 时,您通常会在那里注入一个DataSource 或一个EntityManager。 DataSource.getConnection() 方法应该是线程安全的。关于 EntityManager,Spring 将注入一个代理,该代理对不同的线程表现不同,即不同的线程不会共享相同的 JPA 会话。
- What is the best practice, @Repository is enough or adding @Scope('prototype') would be better ?
最佳实践(或者更确切地说是最广泛传播的方法)是只使用@Repository
- I don't see anyone use @Scope('prototype') with @Repository (according to the tutorials, blogs, etc). Is there a well know reason?
原因是创建多个@Repository bean 实例没有任何好处
- What if my DAO class is accessed by multiple large number of threads with very high frequency? (This is the one I concern the most)
再次重申,单例优于为每个请求创建一个新对象。只是避免冗余同步,这样你的线程就不会在某些监视器上阻塞
用@Repository 注释的组件应该是单例的,因为它在其整个生命周期中永远不会有 multiple/different 状态。是的,它可以保持的唯一状态是连接对象,在创建对象期间将只设置一次。并且它将包含 logic/method(s) 以与数据存储对话,并且每个方法将 take/return 所需的数据对象。因此不需要有多个存储库实例。
上下文:Web 应用程序
我以前没用过Spring,但根据Spring文档,所有bean都是singleton
,除非我们将它们声明为prototype
。
- 不使用 Spring:
通常我会在调用 business/service 层时实例化新的 DAO。 如果它是一个 RESTfull 服务,我实例化几乎所有依赖调用的对象。
- 与Spring:
我可以使用 @Repository
注释数据访问 classes 并且我可以将 @Service
用于服务层 classes.
所以我的带有上述注释的 classes 默认是 singleton
。
有一个 @Scope
注释,我们可以将它们声明为原型,但似乎没有人这样做。
- 没有Spring:每次
new Object();
- 与Spring:
singleton
我的问题是,
- 我之前使用的方式(每次创建新实例)不正确?
- 如果
@Repository
是singleton
,当没有这样的事情时,它如何处理线程安全? (假设它是由 spring 个代理完成的) - 最佳做法是什么,
@Repository
就够了还是加@Scope('prototype')
会更好? - 我没看到有人将
@Scope('prototype')
与@Repository
一起使用(根据教程、博客等)。有什么众所周知的原因吗? - 如果我的 DAO class 被多个大量线程以非常高的频率访问怎么办? (这是我最关心的)
谢谢
不,但是单元测试要难得多,这就是依赖注入的全部意义所在。通过在服务中注入 DAO,您可以通过在测试期间注入模拟 DAO 轻松地对服务进行单元测试。如果服务创建自己的 DAO,那是不可能的。
存储库通常是完全无状态的,除了线程安全的实体管理器、会话工厂或 JDBC 在启动时初始化的模板,因此并发调用不是问题:它是线程-安全。
存储库没有理由成为原型。将原型 DAO 注入到单例服务中仍然会导致每个原型无论如何都被并发调用。
没有理由去做。
没问题:如果编码正确,它应该是线程安全的。
Spring 不会为您处理并发问题。这不是故意的。它所做的只是让您控制创建实例的数量,以便您的应用程序可以正常工作。
单例作用域(很明显)将只创建给定 bean 的一个实例并将其传递给所有相关对象。
每个依赖对象的原型范围将创建自己的实例,不在其他对象之间共享。
对于 DAO 对象,您不太可能需要多个实例来与数据库通信。所以单例经常被使用。
你是对的 - 在 Spring 世界中大多数 bean 都是单例。
- The way I used before (creating new instance each time) is incorrect ?
没有错,因为它有效。它的问题是你在每个请求上实例化一个新的 DAO 实例——在某些情况下它可能很昂贵,而且无论如何它没有任何意义——你为什么需要一堆 DAO 实例? 另一方面,Spring 不仅创建单例,而且将 DAO 注入服务或其他 DAO e.t.c。即为您做了很多工作
- If @Repository is singleton, how does it handle thread safety when there is no such a thing addressed? (Assume it is done by spring proxies)
当您编写@Repository bean 时,您通常会在那里注入一个DataSource 或一个EntityManager。 DataSource.getConnection() 方法应该是线程安全的。关于 EntityManager,Spring 将注入一个代理,该代理对不同的线程表现不同,即不同的线程不会共享相同的 JPA 会话。
- What is the best practice, @Repository is enough or adding @Scope('prototype') would be better ?
最佳实践(或者更确切地说是最广泛传播的方法)是只使用@Repository
- I don't see anyone use @Scope('prototype') with @Repository (according to the tutorials, blogs, etc). Is there a well know reason?
原因是创建多个@Repository bean 实例没有任何好处
- What if my DAO class is accessed by multiple large number of threads with very high frequency? (This is the one I concern the most)
再次重申,单例优于为每个请求创建一个新对象。只是避免冗余同步,这样你的线程就不会在某些监视器上阻塞
用@Repository 注释的组件应该是单例的,因为它在其整个生命周期中永远不会有 multiple/different 状态。是的,它可以保持的唯一状态是连接对象,在创建对象期间将只设置一次。并且它将包含 logic/method(s) 以与数据存储对话,并且每个方法将 take/return 所需的数据对象。因此不需要有多个存储库实例。