【发布时间】:2016-01-16 18:50:14
【问题描述】:
我最近一直在研究一些 Web 应用程序和 REST Web 服务(Spring IoC/MVC/Data JPA 等)。它们通常遵循相同的模式:控制器类 --> 服务类(自动装配了几个“实用程序”/业务逻辑类)--> Spring Data Repositories。
上面几乎所有的类都是 Spring 单例。我觉得这会使类中的代码和某些功能更脏;例如,我不能在一个类中有一个状态,我需要在方法之间传递很多参数,而且我真的不喜欢超过 1-2 个参数(虽然我知道有时这是必要的)。
我想知道如何在大型(例如企业)类型的应用程序中克服这个问题。
- 在 Spring 应用程序中使用非 Spring 托管类是一种常见的做法吗?如果是这样,您如何将依赖项传递给它(通常会自动装配的那些)?例如,如果我使用构造函数注入,那么我需要将所有必要的依赖项自动连接到创建对象的类中,我想避免这种情况。此外,我真的不想在加载时间编织等方面搞乱,以便将 bean 自动装配到非 Spring 对象中。
- 使用原型作用域 bean 是一个好的解决方案吗?唯一的事情是我需要使用 AOP 的作用域代理(或方法注入等)来确保我首先为任何自动装配到单例中的 bean 获得一个新实例。这是一个“干净”且可靠的选择(即,确定不会存在并发类型的问题)吗?我仍然可以毫无问题地将任何单例自动装配到这些类中吗?
是否有人在大型系统上工作(并且实际上设法保持结构不“臃肿”和干净)有任何建议吗?也许有一些我不知道但可以使用的模式?
任何帮助表示赞赏。
【问题讨论】:
-
“类中不能有状态”是什么意思?一般来说,基础设施位被认为是“设置”状态,在 bean 实例化时设置,但在其生命周期内保持不变。
-
我的意思是我不能在 Spring 单例中包含实例变量,因为据我所知它们不是线程安全的。
-
使用实例变量是非常安全和习惯的;查看任何 Spring 教程(包括官方入门指南)。只要在启动时配置好一切,就没有线程问题。
-
可能有几种方法可以做到这一点。一种是自定义作用域,另一种是使用对象来表示要处理的事物,这些对象封装了所有需要的状态,并且可能具有对服务的引用,或者可以注入服务。对于第一种方法,我发现尝试DIY-DI 来了解什么是自定义范围非常有用。第二种方法(在我看来)是使用double dispatch pattern 的结果。
-
@Augusto 看起来整个问题是对bean生命周期误解的结果;最简单的方法(使用在启动期间初始化的实例变量)非常好。