Spring @Repository最佳实践

时间:2015-01-20 07:33:29

标签: java multithreading spring spring-mvc

上下文:Web应用程序

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

  • 不使用Spring:

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

  • 用Spring:

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

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

  • 没有春天:每次new Object();
  • 使用Spring:singleton

我的问题是,

  1. 我之前使用的方式(每次创建新实例)不正确?
  2. 如果@Repositorysingleton,那么在没有这样的问题时它如何处理线程安全? (假设它由弹簧代理完成)
  3. 什么是最佳做法, @Repository已经足够,或者添加@Scope('prototype')会更好吗?
  4. 我没有看到有人@Scope('prototype')使用@Repository(根据教程,博客等)。有一个众所周知的原因吗?
  5. 如果我的DAO类被多个大量频率的线程访问怎么办? (这是我最关心的一个)
  6. 由于

4 个答案:

答案 0 :(得分:22)

你是正确的 - 在 Spring 世界中,大部分豆子都是单身。

  
      
  1. 我之前使用的方式(每次创建新实例)不正确?
  2.   

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

  
      
  1. 如果@Repository是单例,当没有这样的东西被解决时,它如何处理线程安全? (假设它由弹簧代理完成)
  2.   

当您编写@Repository bean时,通常会注入 DataSource EntityManager 。 DataSource.getConnection()方法应该是线程安全的。关于 EntityManager Spring 将注入一个代理,它对不同的线程表现不同,即不同的线程不会共享同一个JPA会话。

  
      
  1. 最佳做法是什么,@存储库已经足够或者添加@Scope('原型')会更好?
  2.   

最佳实践(或者更广泛的方法)是使用@Repository

  
      
  1. 我没有看到任何人使用@Scope(' prototype')和@Repository(根据教程,博客等)。有一个众所周知的原因吗?
  2.   

原因是创建@Repository bean的多个实例

没有任何好处
  
      
  1. 如果我的DAO类被多个大量频率的线程访问怎么办? (这是我最关心的一个)
  2.   

这里再次使用singleton比为每个请求创建一个新对象更好。只是避免冗余同步,这样你的线程就不会在某个监视器上阻塞

答案 1 :(得分:1)

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

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

    < / LI>
  3. 没有理由将存储库作为原型。将原型DAO注入单件服务仍然会导致每个原型同时被调用。

  4. 没有理由这样做。

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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

Singleton范围(显而易见)将只创建给定bean的一个实例并将其传递给所有依赖对象。

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

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