V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
csw3983931
V2EX  ›  程序员

奇思妙想,一个想法,不知道是不是可行的

  •  
  •   csw3983931 · 269 天前 · 2325 次点击
    这是一个创建于 269 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我是一个 Java 程序员,用 spring boot 框架,常常会用 @Autowired 注解去引入各种 service 或者 mapper 我觉得很麻烦呀,有没有不通过 @Autowired 或者我引入一个 baseService 就引入了所有的 bean 。

    我想所有的注册 bean 都会到 spring boot 进行管理,那么为什么 spring boot 不提供一个默认引入所有,然后想用什么就用什么,不用每个都要 @Autowired 一下。

    当然我不是说从 spring boot 上下文通过 getBean 的方式去拿,那样太不优雅了。

    有没有这样比如举一个列子 这是我想要的😍

    
    @Component
    public class ServiceB {
    
    
        @Autowired
        private BaseService baseService;
    
        
        public Order void queryOrder() {
            User user = baseService.UserSerice.getUser();
            Order order = baseService.OrderService.getOrderByUserId(user.getId());
            return order;
        }
    }
    
    

    引入我感觉有时候业务超级复杂,然后慢慢的会变成 @Autowired 地狱,比如会有这样的情况

    这是不是我想要的😨

    
    @Component
    public class ServiceB {
    
    
        @Autowired
        private UserSerice userSerice;
    
        @Autowired
        private OrderService orderService;
    
        public Order void queryOrder() {
            User user = userSerice.getUser();
            Order order = orderService.getOrderByUserId(user.getId());
            return order;
        }
    }
    

    这个随便写的,就是举个列子

    第 1 条附言  ·  268 天前
    统一回复一下吧

    的确我的想法可能是比较少的情况出现才会出现我这样的想法,而且有我这个想法在 Spring boot 程序之上已经是不合理了,理当应该减少 service 循环依赖,理当应该相关的 mapper 引入只能在对应的 service 里面,而随意引入 mapper 。

    但是既然 service 能随意引入其他 mapper 是程序允许的,而且老板要的是今天需求明天上线,很多时候为了快,我真的很无奈,所以我宁愿牺牲程序的性能,也让代码可读性相对来说很算不错。只能出此下策。

    不知道有没有人遇到一个 service 引入几十个 mapper 和 service 。你说重构能有重构时间,我能想出这想法嘛。。
    19 条回复    2023-08-03 09:23:52 +08:00
    forbreak
        1
    forbreak  
       269 天前
    那你把 getBean 封装下,做成动态生成,就能达到你要的效果了吧。
    csw3983931
        2
    csw3983931  
    OP
       269 天前
    @forbreak 要代码提示。比如我输入 baseService.U 要提示 baseService.UserSerice ,感觉通过 Lombok 提前生成一个类,把所有的 bean 都放进去,感觉应该可行
    oneisall8955
        3
    oneisall8955  
       269 天前
    100%循环依赖
    csw3983931
        4
    csw3983931  
    OP
       269 天前
    @oneisall8955 是的 🤣
    arvinsilm
        5
    arvinsilm  
       269 天前
    这和用上下文去拿有什么区别?
    你可以自己写个 BaseService ,再搞个自动生成,把所有 Service 都在 BaseService 里实现一个返回方法。
    mgzu
        6
    mgzu  
       269 天前
    弊大于利,依赖关系不够清晰,循环依赖
    csw3983931
        7
    csw3983931  
    OP
       269 天前
    @arvinsilm getBean 去拿感觉比较繁琐,每次都要 context.getBean(ServiceB.class)
    gogo789
        8
    gogo789  
       269 天前
    看问题感觉你就是想干掉 autowired 。spring 提供依赖注入和依赖查找,autowired 只能说是依赖注入的一种方式,你说的可以通过依赖查询解决就是 BeanFactory.getBean ,但是你觉得不优雅,那就换一个依赖注入的方式,直接用构造器注入,这样就不用写 autowired 了,结合 lombok 的注解的话更方便。
    kingstar718
        9
    kingstar718  
       269 天前
    @gogo789 同意,使用 lambok 的 @RequiredArgsConstructor 注解在类上,引入 bean 直接就是 private final xxService
    gogo789
        10
    gogo789  
       269 天前
    不太建议你搞一个包含所有 bean 的 baseService ,因为 BeanFactory 干的就是这个事,你没必要自己再封装一层
    whooami
        11
    whooami  
       269 天前   ❤️ 1
    我也有一个奇思妙想。能不能一行代码实现我老板的所有需求。
    bruce0
        12
    bruce0  
       269 天前
    偏个楼 Autowired 真的是一个 V 站用户, 能被 @ 到🤣🤣🤣
    yule111222
        13
    yule111222  
       269 天前
    你不如换个想法,把你这些 service 的方法都变成 static 的,没开玩笑
    mineqiqi
        14
    mineqiqi  
       269 天前
    @bruce0 @Autowired 我试试
    newaccount
        15
    newaccount  
       269 天前
    1. 全部引入,循环逃不掉,没得耍
    2. 既然你知道用 lombok ,那么为什么不在 service 头上直接一个 @ RequiredArgsConstructor 了事儿
    3. service 作为业务节点,如果需要 service 相互引用,嗯,大部分情况是设计出了问题
    nothingistrue
        16
    nothingistrue  
       269 天前
    对于楼主本身,11 楼 whooami 的回复就足够了。

    然后从技术上面说一下。

    第一个层面,假如只是不想要 @Autowired ,但是还保留成员变量定义。那么你是必须留着 @Autowired 的,因为并不是所有的成员变量都是自动注入的(尤其是有状态 Bean 的时候)且没有什么好的约定能代替配置来区分它们,所以你必须显式的声明它要被自动注入。当然也不是没有替代措施,当你定义了构造器的时候,那就有了通过构造器自动注入的约定,这时候就可以省略掉 @Autowired 这个显式声明。构造器自动注入,也是 Spring 官方推荐的自动注入方式,但是构造器注入的可读性,不如直接在成员变量上声明 @Autowired 好。

    在第一个层面,恰恰相反,必要的显式声明 @Autowired 不是地狱,隐式强制对 Bean 的所有成员变量做自动注入,才是地狱。

    第二个层面,假如是连成员变量定义都不想定义,继承 baseService 就能自动引入所有 Bean 。这本质上相当于把所有 Bean 整合成同一个类型了,已经将 Java 返祖成原始的 C 了,根本无法作出技术回复。
    yesterdaysun
        17
    yesterdaysun  
       269 天前
    我大概能理解 OP 的思路, 很多年前我做一个 C#的项目的时候, 那时候是架构师自己搭的框架, 思路就是所有的 Service 放到一个静态类里面, 比如叫 ApplicationServiceManager, 简称 ASM, 任何时候要用的时候直接 ASM.UserService.GetUser()就行, 其实用起来也挺爽的, 要用的是时候直接 ASM 点 XXX 出来所有的 Service, 当时架构找呢么解决初始化和循环依赖的我已经忘了, 但是至少这条路是可行的

    但是我还是觉得这套思路和现行的 Spring 体系不太搭, 就像楼上说的, 现在只要用 lombok 配合构造器注入, 几乎是无感的引入需要的 Service, 感觉挺简洁的, 那套集中式的 Service 管理感觉要自己在底层架构引入很多额外的约定和设计才能做出来, 感觉也比较重, 也不利于代码维护和单元测试

    总之相比之下我还是偏向普通 Spring 的注入体系
    minamike
        18
    minamike  
       268 天前 via iPhone
    为什么不问问神奇的 ChatGPT 呢
    xausky
        19
    xausky  
       268 天前
    有依赖地狱就是本身设计的不好,一般多个分层从 controller 到 mapper 中间不管多少层调用的时候一定得是从上到下的,平级调用要谨慎,逆向调用要禁止。你如果是我管不,我就是要我想要的这个方案,那么你直接全部注入 ApplicationContext 然后 getBean 就好了。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2747 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 10:21 · PVG 18:21 · LAX 03:21 · JFK 06:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.