V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
v2defe
V2EX  ›  问与答

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

  •  
  •   v2defe · 2023-07-04 11:07:35 +08:00 · 867 次点击
    这是一个创建于 542 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    问题描述

    为了实现这样的业务方法: 执行一个很复杂的处理方法,现在是一个很长很长的方法. 然后我想对这个方法进行拆分, 拆成一个个小方法, 但是拆分过后, 会产生大量小对象(例如 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, 还是感觉不够优雅. 我还是更想要能够有一个类似有一定作用域的上下文, 我在这个作用域内可以自由使用这些私有变量.

    tedzhou1221
        1
    tedzhou1221  
       2023-07-04 12:06:23 +08:00
    我用的是第二种思路。

    可以考虑开源的规则引擎项目 liteflow 。可以用多种方式从上下文件中获取你想要的对象。
    v2defe
        2
    v2defe  
    OP
       2023-07-04 14:19:37 +08:00
    @tedzhou1221 #1 看了一下 litefow ,确实也是第二种思路,将参数转化为 context 了。貌似大多数项目也都是这种思路,也想看看不同人有没有不同的见解。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4602 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 09:56 · PVG 17:56 · LAX 01:56 · JFK 04:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.