2010-05-25 68 views
5

我希望能够指定一个对象的成员变量是不可变的,一旦对象已被“初始化”,这对我来说意味着它被注入任何依赖关系后,并已执行任何其他初始化操作,它只能在DI之后执行。依赖注入后的不变性,初始化

是否有语言满足我的兴趣 - 以这种方式正式化DI,初始化和支持不变性?也许让他们成为语言的一部分是愚蠢的;也许不会。我不确定。

今天我用Java编程,但我几乎不能使用“final”,因为这些阶段发生在构造函数完成执行之后。有关如何获得我想要的Java的建议?我想我可以让我的对象实现一个基类,以便这些阶段在构造函数完成之前发生,或者使用方面来完成。

想法?

回答

3

我猜这取决于你想要的不变性。如果你想要保证线程安全(所有的东西都必须声明为最终的,包括依赖),那么我认为工厂,构建器或构造器注入是你唯一的选择。

如果你只是想要状态的不变性,那么声明状态变量最终应该是足够的。即使不可变的String类在其实现中也有一个可变字段(哈希码值的缓存)。只要你的代码确保一个实例在没有注入的情况下不可用,所有的都应该是好的。

+0

我只是想清楚哪些成员是可变的,哪些不是。 奇怪,但我从来没有想过如何setter注入不可兼容的不变状态。那么,当我写这个问题的时候,我没有想过,至少:-) – Ladlestein 2010-05-26 02:06:48

0

在Java中,如果你正在使用mutator方法来进行设置,那么在初始化对象时添加逻辑以防止更改会很便宜(尽管在我眼中也很丑)。

public void setMyProperty(String newValue) { 
    checkInitialized(); 
    myProperty = newValue; 
} 

public void checkInitialized() { 
    if (initialized) { 
     throw new IllegalStateException("Setter called after initialization"); 
    } 
} 

尽管这是给予动态检查。它不会给你任何你已经拥有的静态反馈。

4

有产生不可变对象的方式主要有两种:

  1. 使用Builder /工厂模式 - 生成器可以是可变的,但它创建的对象是不可改变的,通常与最终实现的领域。你也可以将两者结合起来,因此对象本身被用来构建新的实例,通常通过改变单独新实例上的状态的“变种”方法。 Spring的FactoryBean就是一个例子。

  2. 创建一个MutableObject子类,它维护一个可变状态标志。所有的mutators在进行任何更改之前都会检查可变状态 - 如果该对象已设置为不可变,则该检查会引发异常,否则更改将继续。

第一种方法完全以Spring为中心,因为它需要实现弹簧专用接口。您可以通过bean上的factory-method/factory-bean属性来创建常规bean的工厂bean,这会从代码中删除弹簧依赖项。

使用第二种方法对弹簧特别有用。您可以指示spring在bean初始化后调用方法,例如密封物体的密封()使其不可变。或者,你可以实现一个小的BeanFactoryPostProcessor来自动完成,而不必记得设置init-method =“seal”。在每个不可变的bean上。

+0

您的回答很有帮助;我已经选择了另一个,因为它说“构造函数注入”,这对我来说更好一些。 – Ladlestein 2010-05-26 01:52:33

+0

我想使用“最终”或者用另一种语言,任何机制表示并强制不变。在Java中,Builder对我有帮助吗?是不是使用必要的构造函数注入来使用final? – Ladlestein 2010-05-26 02:10:42

+0

构建器可以使用setter注入,并使用构造函数注入产生对象。 C.F. Spring中的大多数FactoryBean实现 - 它们使用setter注入进行配置。 – mdma 2010-05-26 09:58:40

1

在Java中,您可以使用builder在其构造函数中初始化一个不可变的对象,因此您会避开setter。

如果您使用Scala,但不可变性为the default

+0

正如我上面所说的,Builder是如何帮助的,在我看来Builder并不相关,除非我使用构造函数注入。 – Ladlestein 2010-05-26 02:11:27

+0

确切的说,这就是为什么我说“避开二传手”。 – 2010-05-26 10:29:10

0

要指定一个类是不可变的,可以使用@Immutable注释。

您可以看到Javadoc here

这适用于Eclipse中的Findbugs插件。

@Alexander:

据我了解他,他问如何指定一个类是不可变的。不是如何写一个不可变的类。此注释可以为您提供工具支持,以验证您的班级中没有您声称是不可变的错误。

距离的Javadoc片段:

必要性。这意味着所有 公共领域是最终的,并且所有 公开的最终参考字段参考 其他不可变对象

+0

-1。啊哈!有没有'@ NoBugs'注释? :) – 2010-05-25 20:42:39

+1

公平点。 Downvote删除。 – 2010-05-25 21:05:14

相关问题