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

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

  •  
  •   csw3983931 · 2023-08-02 14:12:55 +08:00 · 2553 次点击
    这是一个创建于 470 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我是一个 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 条附言  ·  2023-08-03 09:22:29 +08:00
    统一回复一下吧

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

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

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

    然后从技术上面说一下。

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

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

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

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

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