依赖注入、初始化后的不变性
我希望能够指定对象的成员变量在对象被“初始化”后是不可变的,这对我来说意味着在注入任何依赖项并执行它只能执行的任何其他初始化操作之后DI 之后。
是否有语言能够满足我的兴趣——以这种方式形式化 DI、初始化并支持不变性?也许让它们成为语言的一部分是愚蠢的;也许不是。我不知道。
今天我用 Java 编程,但我几乎不能像我希望的那样使用“final”,因为这些阶段发生在构造函数完成执行之后。关于如何使用 Java 获得我想要的东西有什么建议吗?我想我可以让我的对象实现一个基类,以便这些阶段在构造函数完成之前发生,或者使用方面来执行相同的操作。
想法?
I'd like to be able to specify that an object's member variables are immutable once the object has been "initialized", which to me means after it has been injected with any dependencies, and has performed any other initialization operations that it can only perform after DI.
Are there languages that satisfy my interest - that formalize DI, initialization, and support immutability in this fashion? Maybe it's dumb to make them a part of a language; maybe not. I'm not sure.
Today I program in Java, but I can't use "final" nearly as much as I'd like, because those phases happen after the constructor has finished execution. Any advice on how to get what I want with Java? I guess I could have my objects implement a base class so that those phases happen before the constructor finishes, or use aspects to do the same.
Thoughts?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
生成不可变对象有两种主要方法:
使用构建器/工厂模式 - 构建器可能是可变的,但它创建的对象是不可变的,通常使用 Final 字段实现。您还可以将两者结合起来,因此对象本身用于构建新实例,通常通过“mutator”方法来更改单独的新实例上的状态。 Spring 的
FactoryBean
就是一个例子。创建一个 MutableObject 子类,它维护可变状态的标志。所有的修改器在进行任何更改之前都会检查可变状态 - 如果对象已设置为不可变,则检查会引发异常,否则更改将继续。
第一种方法完全以 Spring 为中心,因为它需要实现特定于 spring 的接口。您可以通过 bean 上的
factory-method
/factory-bean
属性创建常规 bean 工厂 bean,这会从代码中删除 spring 依赖项。使用第二种方法对于 spring 特别有用。您可以指示 spring 在 bean 初始化后调用一个方法,例如 seal() 密封对象 - 使其不可变。或者,您可以实现一个小型 BeanFactoryPostProcessor 来自动执行此操作,而无需记住设置 init-method="seal"。在每个不可变的 bean 上。
There are two main ways of producing immutable objects:
use the builder/factory pattern - the builder may be mutable, but the objects it creates are immutable, usually implemented with final fields. You can also combine the two, so the object itself is used to build new instances, usually via "mutator" methods that change state on a separate, new instance. Spring's
FactoryBean
is an example of this.create a MutableObject subclass, which maintains a flag for mutable state. All your mutators check the mutable state before making any changes - if the object has been set to immutable, then the check throws an exception, otherwise the change goes ahead.
The first approach is quite Spring-centric, since it requires implmentation of a spring-specific interface. You can create factory beans that are regular beans, via
factory-method
/factory-bean
attributes on a bean, which removes the spring dependency from your code.Using the second approach is particularly useful with spring. You can instruct spring to call a method after bean initialization, e.g. seal() which seals the object - makes it immutable. Alternatively, you can implement a small
BeanFactoryPostProcessor
to do this automatically without having to remember to set the init-method="seal". on each immutable bean.我想这取决于你想要从不变性中得到什么。如果您想要保证线程安全(其中所有内容都必须声明为最终的,包括依赖项),那么我认为工厂、构建器或构造函数注入是您唯一的选择。
然而,如果您只想要状态的不变性,那么将状态变量声明为final就足够了。即使不可变的 String 类在其实现中也有一个可变字段(哈希码值的缓存)。只要您的代码确保实例在没有注入的情况下不可用,一切都应该很好。
I guess it depends on what you want out of the immutability. If you want the guaranteed thread safety (where everything must be declared final, including the dependencies) then I think factory, builder or constructor injection are your only options.
If however you just want immutability of state, then declaring the state variables final should be enough. Even the immutable String class has a mutable field in its implementation (a cache of the hashcode value). As long as your code otherwise ensures that an instance is not available without injection, all should be well.
在 Java 中,您可以使用 构建器在其构造函数中初始化一个不可变的对象,因此您会回避设置器。
不过,如果您使用 Scala,则不变性是默认值。
In Java, you can use a builder to initialize an immutable object in its constructor, so you'd shy away from setters.
If you use Scala, though, immutability is the default.
在 Java 中,如果您无论如何都使用 mutator 方法来进行设置,那么在对象初始化后添加逻辑以防止更改是相当便宜的(尽管在我看来也相当难看)。
尽管这充其量只是进行动态检查。它不会给你任何关于你已经拥有的静态反馈。
In Java, if you're using mutator methods to do your setting anyhow, it's pretty cheap (though also pretty ugly in my eyes) to add logic to prevent alterations once the object is initialized.
At best though this is giving a dynamic check. It doesn't give you any static feedback over what you would have already had.
要指定类是不可变的,可以使用 @Immutable 注解。
您可以在此处查看 Javadoc。
这与 Eclipse 中的 Findbugs 插件配合得很好。
@Alexander:
据我了解,他问如何指定一个类是不可变的。不是如何编写不可变的类。此注释可以为您提供工具支持,以验证您的类中没有您声称不可变的错误。
Javadoc 的片段:
To specify that a class is immutable, you can use the
@Immutable
annotation.You can see the Javadoc here.
This works well with the Findbugs plugin in Eclipse.
@Alexander:
As I understand him, he asked how to specify that a class is immutable. Not how to write an immutable class. This annotation can give you tool support to verify that you don't have a bug in your class that you claims are immutable.
A snippet from the Javadoc: