【问题标题】:Immutable objects and Spring/Spring MVC: the right choice?不可变对象和 Spring/Spring MVC:正确的选择?
【发布时间】:2017-10-05 22:42:37
【问题描述】:

我通常尝试将我的类设计为不可变类,因此在编码压力方面我有很多优势。

但是在使用 Spring 时,我有时会注意到框架在大多数情况下“不鼓励”这种设计,而是支持经典的 JavaBeans 设计:默认构造函数 + getters/setters强>。

我真的不喜欢 JavaBean 设计的对象,因为它们的疯狂 可变性。 所以我想知道我是否遗漏了什么......

我试图让我的类设计尽可能优雅和可重用,但框架需要更改此设计或以困难的方式允许它...

这是怎么回事?

【问题讨论】:

  • 春天一般不会鼓励或阻止任何事情,所以我想知道你为什么这么认为。没有什么可以阻止您在 bean 中进行构造函数注入而不是 setter 注入(您也可以进行基于字段的注入)。唯一需要 getter/setter 的地方是在 web 层中进行数据绑定,但这适用于所有 web 框架,包括 JSF、Struts 等。
  • 我认为您考虑的是 Web 绑定而不是 bean 创建,对吧?
  • 如果您担心绑定到表单的视图模型类是可变的,Spring 也允许您使用不可变的视图模型类。您必须编写将表单字段转换为模型对象的代码。您需要为从表单字段填充的每个模型类编写类。这意味着您需要权衡不可变性的优势与 Spring MVC 提供的带有可变对象的自动表单绑定的优势。
  • @M.Deinum 是的,我说的是 Web 层端的数据绑定,还有模型/持久性端。
  • @davioooh 模型持久化方面不是Spring处理的,所以前面的抱怨应该针对当前的ORM。当涉及到 Web 绑定时,是的,开箱即用不支持不变性,但您可以在需要时编写自己的代码

标签: java spring spring-mvc


【解决方案1】:

对于 web 表单数据绑定(即表单 POST),问题是 Java 反射在构造函数上很弱,因此很难在没有注释的情况下进行数据绑定。很久以前,我考虑提交一个错误,即 Springs 数据绑定应该利用经常被遗忘的@ConstructorProperties(iirc 我曾考虑自己做补丁,但它相当复杂并且会破坏很多东西)。应该有人提出功能请求。

顺便说一句,我说的是 Web 数据绑定(而不是依赖注入),因为 Spring 长期以来一直非常支持基于构造函数的 DI(不可变对象需要基于构造函数的注入)。事实上,我会说基于构造函数的注入或(静态方法工厂)正在成为优于传统 getter/setter 组件的首选实践(您可以在多年来的许多 Spring 类中看到这一点,这些变化正在转向 final 和构造函数)。

无论如何,我能够使用 Jackson https://gist.github.com/agentgt/4458079 对不可变对象进行 Web 数据绑定

(虽然它使用 Jackson 进行数据绑定,但请求不必是 JSON)

您可能还想查看 Spring Webflow DataBinding to immutable objects via a constructor? 我最初提出的要点并提供更多信息。

【讨论】:

  • Spring 并没有真正的偏好,特别是最近,必需的依赖项是通过构造函数参数注入的,而不是将其作为选项(后来检查了 afterPropertiesSet 的方法) InitializingBean).
  • 我说首选,因为我在 Spring AMQP、Spring Integration 和新的 Spring Boot 等项目中注意到使用基于构造函数的注入或类似的东西并使用 final 字段。鉴于今天的 JVM 内存模型和对大规模并发性的推动,我想说的是,与 6 年前几乎没有完成相比,大多数 Java 程序员正在朝着不可变的方向发展。
  • 同意。但据我所知,这仅适用于所需的依赖项或没有默认值的依赖项。但也许现在这一点更加明显,尤其是在使用配置类时。
【解决方案2】:

我有时会创建单独的不可变“设计模型”类和可变(Java Bean)“MVC 模型”类来避免这些问题。

【讨论】:

    【解决方案3】:

    它使用依赖注入将对象注入其他对象。所以如果这些其他对象是不可变的,它就不能改变它们的状态。

    【讨论】:

    • 这是不正确的,因为可以将依赖项作为构造函数参数注入,从而保持所有 Spring 托管 bean 不可变。当存在需要循环依赖的合法场景(A 依赖于 B 而后者又依赖于A)时,Setter(基于属性)注入(使对象可变)变得有用。
    • 使用@Autowired 之类的注解怎么样?
    • @manish 我不会将循环依赖称为合法场景,而是一种设计气味......
    • 同意,但存在需要循环依赖的有效场景。
    • 循环依赖在我的书中是不行的,通常是糟糕的设计(或古老的图书馆)的问题。
    猜你喜欢
    • 1970-01-01
    • 2014-10-15
    • 2010-10-16
    • 1970-01-01
    • 2011-05-08
    • 1970-01-01
    • 2011-02-15
    • 1970-01-01
    • 2012-09-06
    相关资源
    最近更新 更多