请教下在 Spring 环境中上下文传递的优雅方式?

314 天前
 v2defe

请教下这种情况下有什么更优雅的实现方式吗?

问题描述

为了实现这样的业务方法: 执行一个很复杂的处理方法,现在是一个很长很长的方法. 然后我想对这个方法进行拆分, 拆成一个个小方法, 但是拆分过后, 会产生大量小对象(例如 Foo1 、Foo2)在方法间传递, 并且这些小对象是在当前方法中会普遍使用到的,我想让这些小对象在当前处理过程作用域内共享, 类似于上下文.

第一种思路

我把小对象定义为 private field, 供对象内实例方法共享使用. 但是在这个对象中, 我还需要去注入由 Spring 管理的 bean 来使用 bean 方法.

这种思路的问题是注入 bean 的方法很麻烦, 但小对象的使用很方便, 在任何方法内都可以直接用而不需要传递.

<details> <summary>展开代码实现</summary>
public class BuildTreeCommand {

    // 作为对象私有变量来使用
    private Foo1 foo1;
    // 作为对象私有变量来使用
    private Foo2 foo2;

    // bean
    private final AService aService;
    // bean
    private final BService bService;

    {
        // 通过 Spring 注入 bean
        aService = SpringContextUtil.getBean(AService.class);
        // 通过 Spring 注入 bean
        bService = SpringContextUtil.getBean(BService.class);
    }
    
    public Tree build(){
        // ...调用很多私有方法
        return tree;
    }
    
    private void solve1(){
        // 使用 foo1
        Log.i(foo1);
        // 使用 aService
    }
}

使用方法

Command command = new BuildTreeCommand();
Tree tree = command.build();
</details>

第二种思路

另一种思路是将 BuildTreeCommand 交给 Spring 来管理, 为了解决小对象传递的问题, 使用一个上下文对象包含所有小对象, 这样在方法间只需要传递这个上下文对象, 然后从上下文对象中取值即可(TreadLocal 可能很合适).

<details> <summary>展开代码实现</summary>
@Service
public class BuildTreeCommand {


    @Autowired
    private final AService aService;
    @Autowired
    private final BService bService;

    public Tree build() {
        // 调用很多私有方法
        return tree;
    }

    private void solve1(Context context) {
        // 使用 foo1
        Log.i(context.foo1);
        // 使用 aService
    }

    public static class Context {
        public Foo1 foo1;
        public Foo2 foo2;

        // getter setter
    }
}
</details>

这种思路的问题是每一个小对象还得单独 get, 还是感觉不够优雅. 我还是更想要能够有一个类似有一定作用域的上下文, 我在这个作用域内可以自由使用这些私有变量.

658 次点击
所在节点    问与答
2 条回复
tedzhou1221
314 天前
我用的是第二种思路。

可以考虑开源的规则引擎项目 liteflow 。可以用多种方式从上下文件中获取你想要的对象。
v2defe
314 天前
@tedzhou1221 #1 看了一下 litefow ,确实也是第二种思路,将参数转化为 context 了。貌似大多数项目也都是这种思路,也想看看不同人有没有不同的见解。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/953918

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX