java Spring @Repository 最佳实践

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28039901/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 12:54:16  来源:igfitidea点击:

Spring @Repository best practices

javamultithreadingspringspring-mvc

提问by sura2k

Context: Web application

上下文:Web 应用程序

I haven't used Spring before, but according to the Spring docs, all the beans are singleton, unless we declare them as prototype.

我以前没有使用过 Spring,但是根据 Spring 文档,所有的 bean 都是singleton,除非我们将它们声明为prototype.

  • Without using Spring:
  • 不使用弹簧:

Normally I instantiate new DAO when there is a call to the business/service layer. If it is a RESTfull service, I instantiate almost all the objects which depend on the call.

通常,当调用业务/服务层时,我会实例化新的 DAO。如果是 RESTfull 服务,我会实例化几乎所有依赖于调用的对象。

  • With Spring:
  • 与春天:

I can annotate data access classes with @Repositoryand also I can use @Servicefor service layer classes.

我可以注释数据访问类,@Repository也可以@Service用于服务层类。

So my classes with above annotations are singletonby default. There is a @Scopeannotation that we can declare them as prototype, but nobody seems doing this.

所以我的带有上述注释的类是singleton默认的。有一个@Scope注释,我们可以将它们声明为原型,但似乎没有人这样做

  • Without Spring : new Object();each time
  • With Spring: singleton
  • 没有春天:new Object();每次
  • 与春天: singleton

My questions are,

我的问题是,

  1. The way I used before (creating new instance each time) is incorrect ?
  2. If @Repositoryis singleton, how does it handle thread safety when there is no such a thing addressed? (Assume it is done by spring proxies)
  3. What is the best practice, @Repositoryis enough or adding @Scope('prototype')would be better ?
  4. I don't see anyone use @Scope('prototype')with @Repository(according to the tutorials, blogs, etc). Is there a well know reason?
  5. 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)
  1. 我之前使用的方式(每次都创建新实例)不正确?
  2. 如果@Repositorysingleton,当没有解决这样的事情时,它如何处理线程安全?(假设它是由 spring 代理完成的)
  3. 什么是最佳实践, @Repository是否足够或添加@Scope('prototype')会更好?
  4. 我没有看到有人使用@Scope('prototype')with @Repository(根据教程、博客等)。有一个众所周知的原因吗?
  5. 如果我的 DAO 类被多个大量线程以非常高的频率访问怎么办?(这是我最关心的)

Thanks

谢谢

采纳答案by bedrin

You're correct - in Springworld most of the beans are singletons.

你是对的 - 在Spring世界中,大多数 bean 都是单例。

  1. The way I used before (creating new instance each time) is incorrect ?
  1. 我之前使用的方式(每次都创建新实例)不正确?

It is not incorrect since it works. The problem about it is that you instantiate a new instance of DAO on each request - in some cases it might be expensive, and anyway it doesn't make any sense - why would you need a bunch of DAO instances? Spring on the other hand not only creates a singleton but also injects DAO's to services or other DAO's e.t.c. i.e. does a lot of work for you

它没有错,因为它有效。关于它的问题是你在每个请求上实例化一个新的 DAO 实例——在某些情况下它可能很昂贵,无论如何它没有任何意义——你为什么需要一堆 DAO 实例?另一方面,Spring 不仅创建了一个单例,而且还将 DAO 注入服务或其他 DAO 的 etcie 为您做了很多工作

  1. 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)
  1. 如果@Repository 是单例的,如果没有解决这样的事情,它如何处理线程安全?(假设它是由 spring 代理完成的)

When you are writing a @Repository bean, you would normally inject there a DataSourceor an EntityManager. DataSource.getConnection() method should be thread safe. With regard to EntityManager, Springwill inject a proxy which will behave differently for different threads, i.e. different threads won't share the same JPA session.

当您编写 @Repository bean 时,您通常会在那里注入一个DataSource或一个EntityManager。DataSource.getConnection() 方法应该是线程安全的。关于EntityManagerSpring将注入一个代理,该代理对于不同的线程会有不同的行为,即不同的线程不会共享相同的 JPA 会话。

  1. What is the best practice, @Repository is enough or adding @Scope('prototype') would be better ?
  1. 什么是最佳实践,@Repository 就足够了,还是添加 @Scope('prototype') 会更好?

The best practice (or rather a most wide-spread approach) is to just use @Repository

最佳实践(或者更确切地说是最广泛使用的方法)是只使用 @Repository

  1. I don't see anyone use @Scope('prototype') with @Repository (according to the tutorials, blogs, etc). Is there a well know reason?
  1. 我没有看到有人将 @Scope('prototype') 与 @Repository 一起使用(根据教程、博客等)。有一个众所周知的原因吗?

The reason is that there's no profit from creating multiple instances of @Repository beans

原因是创建多个@Repository bean 实例没有任何好处

  1. 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)
  1. 如果我的 DAO 类被多个大量线程以非常高的频率访问怎么办?(这是我最关心的)

Again here singleton is better than creating a new object for each request. Just avoid redundant synchronization so your threads won't block on some monitor

同样,这里的单例比为每个请求创建一个新对象要好。避免冗余同步,这样您的线程就不会在某些监视器上阻塞

回答by Manmay

Components annotated with @Repository should be singleton, because it will never have multiple/different states throughout its lifetime. Yes the only state it can hold is the connection object , which will be set just once during the creation of the object. And It will contain the logic/method(s) to talk to the data store and each method will take/return the data objects required. So it is not required to have multiple instances of repository.

用@Repository 注释的组件应该是单例的,因为它在整个生命周期中永远不会有多个/不同的状态。是的,它可以保持的唯一状态是 connection object ,它将在创建对象期间只设置一次。它将包含与数据存储交谈的逻辑/方法,每个方法将获取/返回所需的数据对象。所以不需要有多个存储库实例。

回答by JB Nizet

  1. No, but it's much harder to unit test, which is what dependency injection is all about. By injecting a DAO in a service, you can easily unit-test the service by injecting a mock DAO during the test. That's not possible if the service creates its own DAO.

  2. A repository is typically completely stateless except for a thread-safe entity manager, session factory or JDBC template initialized at startup time, so being called concurrently is not a problem: it's thread-safe.

  3. There's no reason for a repository to be a prototype. Injecting a prototype DAO into a singleton service will still cause each prototype to be called concurrently anyway.

  4. There's no reason to do it.

  5. No problem: it should be thread-safe if coded correctly.

  1. 不,但是单元测试要困难得多,这就是依赖注入的全部内容。通过在服务中注入 DAO,您可以通过在测试期间注入模拟 DAO 轻松地对服务进行单元测试。如果服务创建自己的 DAO,这是不可能的。

  2. 除了在启动时初始化的线程安全实体管理器、会话工厂或 JDBC 模板之外,存储库通常是完全无状态的,因此并发调用不是问题:它是线程安全的。

  3. 存储库没有理由成为原型。将原型 DAO 注入单例服务仍然会导致每个原型无论如何都被并发调用。

  4. 没有理由这样做。

  5. 没问题:如果编码正确,它应该是线程安全的。

回答by SimY4

Spring doesn't handle concurrency problems for you. It doesn't meant to. All it does is letting you controll the number of creating instances so your application could work propertly.

Spring 不会为您处理并发问题。它不是故意的。它所做的只是让您控制创建实例的数量,以便您的应用程序可以正常工作。

Singleton scope (as obvious) will create only one instance of the given bean and pass it to all dependent objects.

单例范围(很明显)将仅创建给定 bean 的一个实例并将其传递给所有依赖对象。

Prototype scope for each dependent object will create its own instance, not shared between other objects.

每个依赖对象的原型范围将创建自己的实例,而不是在其他对象之间共享。

For DAO objects it's very unlikely that you need multiple instances to communicate with database. So singleton is used mostly always.

对于 DAO 对象,您不太可能需要多个实例来与数据库进行通信。所以单例通常总是被使用。