在 spring 框架中创建有状态对象的一种方法

Lano

Spring 框架作为 Java 社区的主流框架,绝大部分 Java 项目都会使用。但是 Spring 框架其实诞生的很早,在诞生之初主要是为了服务于过程式编程和传统面向对象编程,这些编程方式不需要使用有状态的对象,因此 Spring 的单例 Bean 非常适合。但是现代面向对象编程,强调了对属性的封装,因此都是有状态的对象,不再能把对象交给 Spring 管理。如果只是简单的对于属性的计算,直接 new 创建也无妨。但是难免有些方法需要产生一些副作用,要存数据库、抛事件等。这就需要在对象中依赖一些 Spring 的 Bean。

一种解决方式是,通过 set 方法或者构造函数引入 Spring 的 Bean。这种解决思路是很自然的选择,但是这会让创建对象的地方感觉很诧异,因为其难以理解这些依赖,也会让创建对象的方式很繁琐。

我也尝试过直接使用 Spring 提供的工具类直接在构造函数里获取 Bean。这样调用方就不再需要关心对 Spring Bean 的依赖。但是这其实是一种反模式,违反了依赖注入的范式。

这两种方法各有优劣,是否有一种方式同时获得这两种方法的有点同时避免缺点呢。这个问题我摸索了很久,直到最近使用了一段时间的 Scala 社区的 ZIO 框架以后,找到了灵感。下面先贴出代码的实现。

package lano.whiteboard.application;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

@RequiredArgsConstructor
@Component
public class ModelFactory {
    private final Store store;

    public Model createModel(String data) {
        return new Model(data);
    }

    public class Model {
        private final String data;

        public Model(String data) {
            this.data = data;
        }

        public void newRecord() {
            store.store(this.data);
        }
    }
}

Model 类是我们要创建的有状态对象,它是 ModelFactory 的内部类。我们在 ModelFactory 注入 Model 需要使用的 Spring Bean Store,这样 Model 在执行 newRecord 时就可以直接调用 Store 的方法了。因为不能直接创建 Model 所以提供一个 createModel 方法用于创建 Model 对象。我们在创建 Model 对象时调用方只需要关心 Model 相关的属性,同时不需要关心其它依赖,完美的解决了前文两种方法的弊端。

阅读 235
13 声望
1 粉丝
0 条评论
你知道吗?

13 声望
1 粉丝
文章目录
宣传栏