初始化bean的最佳方法是什么?

时间:2008-10-17 03:21:43

标签: java spring

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

有什么权衡(在编写使用构造函数建立初始状态的bean,或者使用属性以及可能是afterProperties()方法之间)?

5 个答案:

答案 0 :(得分: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

我不确定这符合你的春季要求,但总的来说,我是建筑师的忠实粉丝。

答案 1 :(得分:3)

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

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

答案 2 :(得分: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 Reference Documentation

中找到有关自动装配的更多信息

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

答案 3 :(得分:0)

权衡:

构造: 优点: 可以很简单,尤其是具有三个或更少属性来初始化。 需要担心的一次性,无/最小额外配置。

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

塞特斯: 优点: 子项继承了setter,因此可以轻松覆盖属性以影响构造后的行为。 可以统一指定多个属性,而无需查找不同的方法签名(JavaBeans约定)

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

答案 4 :(得分:0)

你也可以使用@Resource代替@Autowired进行自动装配,这有点像autowire byName所以你不必担心是否有更多相同类型的bean(你也可以处理@Qualifier,但我只建议用来描述bean的特征)。这真的取决于你的用例哪种方式最好,所以你必须根据你的情况进行评估并决定。