10

在 spring 中,您可以通过使 applicationContext.xml 调用构造函数来初始化 bean,或者您可以在 bean 上设置属性。两种方法之间的权衡是什么?拥有一个构造函数(它强制执行在一种方法中拥有所需的一切)更好还是拥有所有属性更好(这使您可以灵活地仅选择性地注入,例如在单元测试时。)

有什么权衡(在编写一个使用构造函数来建立它的初始状态的 bean 或使用属性和可能的​​ afterProperties() 方法之间)?

4

5 回答 5

15

我不确定是否有初始化 bean 的“最佳”方法。我认为两者各有利弊,根据情况,一种或另一种可能是合适的。这当然不是一个详尽的清单,但这里有一些需要考虑的事情。

使用构造函数可以让您拥有一个不可变的 bean。如果您可以将不可变对象适合您的设计,那么它们是很好的。它们不需要线程之间的复制、序列化访问或其他特殊处理。如果你有 setter,你的对象不是不可变的。使用构造函数还可以确保正确初始化对象。构造函数完成后,对象才有效。如果您的对象需要使用 setter 来初始化它,则可能存在无效对象。

另一方面,使用构造函数通常会导致伸缩问题。很多时候你会需要很多不同的构造函数,其中大部分是另一个构造函数的超集。通常这些是为了方便。例如:

public class Person {
  public Person(String name) { ... }
  public Person(String name, String phone) { ... }
  public Person(String name, String phone, String email) { ... }
}

我非常喜欢的一种替代方案是 Josh Bloch 在 JavaOne 提出的所谓的“增强型”构建器模式。您可以在他的“Effective Java, Second Edition”一书中看到这一点。如果您查看该模式的使用方式,它还将解决您的“afterProperties”方法问题。构建器模式将保证对象被正确初始化。

这是讨论该模式的附加博客文章:http ://www.screaming-penguin.com/node/7598

我不确定这是否符合您的弹簧要求,但总的来说,我是 builder 的忠实粉丝。

于 2008-10-17T05:11:04.140 回答
3

IMO 构造函数注入的主要优点是它与不变性兼容。但是,如果一个类有超过 3 个依赖项,这需要提供一个带有大量参数的构造函数,这很笨拙。

在使用 setter-injection 时,我更喜欢使用@PostConstruct注解来标识初始化方法。与您提到的方法相比,这涉及到与 Spring 框架的更松散的耦合afterProperties()(实际上,我认为它是afterPropertiesSet())。另一个选项是<bean>元素的 init 方法属性。

于 2008-10-17T04:50:23.730 回答
2

我不知道您当前使用的版本,但如果是 Spring 2.5,您还可以考虑在某些情况下使用 @Autowired 注释。这粗略仅适用于对其他 bean 的引用,而不适用于字符串等,如 lycony 的示例。

它为您节省了创建 setter 和/或构造函数以及大量配置的负担。一个小例子:

public class MyPersonBean {
  @Autowired
  private PersonManager personManager;

  public void doSomething() {
    this.personManager.doSomething();
  }
}

在您的配置文件中:

<context:annotation-config/>

自动装配是按类型完成的,所以如果你有一个 PersonManager 类型的 bean,它将把它注入到带注释的字段中。如果您有更多该类型的 bean,您可以使用 @Qualifier 注释将它们区分开来......

您可以在Spring 参考文档中找到有关自动装配的更多信息

我在之前的项目中开始将@Autowired 与组件扫描结合使用,我必须说我摆脱了 90% 以上的 Spring 配置文件。

于 2008-10-17T09:08:42.553 回答
0

权衡:

构造函数:好处:可以非常简单,尤其是。具有三个或更少的属性来初始化。一次性,无需/无需担心的额外配置。

缺点:必须为几种情况创建多个构造函数构造函数不是继承的,因此类必须调用 super() 并提供重复的构造函数以允许以前的行为。

Setter:好处:子继承setter,因此可以很容易地覆盖属性以影响构造后的行为。可以以统一的方式指定多个属性,而无需查找不同的方法签名(JavaBeans 约定)

缺点:必须为每个属性显式调用每个 setter。导致某些类显式设置了大量属性。

于 2008-10-18T03:42:31.573 回答
0

您也可以使用@Resourceto autowire 而不是@Autowired,这有点像 autowire byName 所以您不必担心是否有更多具有相同类型的bean(ofc您也可以使用 来处理它@Qualifier,但我只建议描述一个豆的特征)。这实际上取决于您的用例,哪种方式是最好的,因此您必须根据您的情况对其进行评估并做出决定。

于 2009-01-22T15:52:41.113 回答