春季@Repository最佳实践

2022-09-01 05:24:12

上下文:Web 应用程序

我以前没有使用过Spring,但是根据Spring文档,除非我们将它们声明为。singletonprototype

  • 不使用弹簧:

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

  • 带弹簧:

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

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

  • 无弹簧:每次new Object();
  • 带弹簧:singleton

我的问题是,

  1. 我以前使用的方式(每次创建新实例)不正确?
  2. 如果 是 ,当没有解决此类问题时,它如何处理线程安全?(假设它是由弹簧代理完成的)@Repositorysingleton
  3. 什么是最佳实践,是否足够或添加会更好?@Repository@Scope('prototype')
  4. 我没有看到任何人使用(根据教程,博客等)。有众所周知的原因吗?@Scope('prototype')@Repository
  5. 如果我的 DAO 类由多个大量具有非常高频率的线程访问,该怎么办?(这是我最关心的)

谢谢


答案 1

你是对的 - 在春季世界中,大多数豆子都是单例。

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

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

  1. 如果@Repository是单例的,那么当没有解决此类问题时,它如何处理线程安全?(假设它是由弹簧代理完成的)

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

  1. 最佳实践是什么,@Repository就足够了,或者添加@Scope(“原型”)会更好?

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

  1. 我没有看到任何人使用@Scope(“原型”)与@Repository(根据教程,博客等)。有众所周知的原因吗?

原因是创建多个@Repository豆实例没有利润

  1. 如果我的 DAO 类由多个大量具有非常高频率的线程访问,该怎么办?(这是我最关心的)

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


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

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

  3. 存储库没有理由成为原型。将原型 DAO 注入单例服务仍会导致每个原型同时调用。

  4. 没有理由这样做。

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