在 spring 中,您可以通过使 applicationContext.xml 调用构造函数来初始化 bean,或者您可以在 bean 上设置属性。两种方法之间的权衡是什么?拥有一个构造函数(它强制执行在一种方法中拥有所需的一切)更好还是拥有所有属性更好(这使您可以灵活地仅选择性地注入,例如在单元测试时。)
有什么权衡(在编写一个使用构造函数来建立它的初始状态的 bean 或使用属性和可能的 afterProperties() 方法之间)?
我不确定是否有初始化 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 的忠实粉丝。
IMO 构造函数注入的主要优点是它与不变性兼容。但是,如果一个类有超过 3 个依赖项,这需要提供一个带有大量参数的构造函数,这很笨拙。
在使用 setter-injection 时,我更喜欢使用@PostConstruct
注解来标识初始化方法。与您提到的方法相比,这涉及到与 Spring 框架的更松散的耦合afterProperties()
(实际上,我认为它是afterPropertiesSet()
)。另一个选项是<bean>
元素的 init 方法属性。
我不知道您当前使用的版本,但如果是 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 配置文件。
权衡:
构造函数:好处:可以非常简单,尤其是。具有三个或更少的属性来初始化。一次性,无需/无需担心的额外配置。
缺点:必须为几种情况创建多个构造函数构造函数不是继承的,因此类必须调用 super() 并提供重复的构造函数以允许以前的行为。
Setter:好处:子继承setter,因此可以很容易地覆盖属性以影响构造后的行为。可以以统一的方式指定多个属性,而无需查找不同的方法签名(JavaBeans 约定)
缺点:必须为每个属性显式调用每个 setter。导致某些类显式设置了大量属性。
您也可以使用@Resource
to autowire 而不是@Autowired
,这有点像 autowire byName 所以您不必担心是否有更多具有相同类型的bean(ofc您也可以使用 来处理它@Qualifier
,但我只建议描述一个豆的特征)。这实际上取决于您的用例,哪种方式是最好的,因此您必须根据您的情况对其进行评估并做出决定。