• 请不要在回答技术问题时复制粘贴 AI 生成的内容
csw3983931
V2EX  ›  程序员

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

  •  
  •   csw3983931 · Aug 2, 2023 · 3419 views
    This topic created in 1024 days ago, the information mentioned may be changed or developed.

    我是一个 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;
        }
    }
    

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

    Supplement 1  ·  Aug 3, 2023
    统一回复一下吧

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

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

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

    然后从技术上面说一下。

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

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

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

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

    总之相比之下我还是偏向普通 Spring 的注入体系
    minamike
        18
    minamike  
       Aug 2, 2023 via iPhone
    为什么不问问神奇的 ChatGPT 呢
    irrigate2554
        19
    irrigate2554  
       Aug 3, 2023
    有依赖地狱就是本身设计的不好,一般多个分层从 controller 到 mapper 中间不管多少层调用的时候一定得是从上到下的,平级调用要谨慎,逆向调用要禁止。你如果是我管不,我就是要我想要的这个方案,那么你直接全部注入 ApplicationContext 然后 getBean 就好了。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3900 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 72ms · UTC 00:12 · PVG 08:12 · LAX 17:12 · JFK 20:12
    ♥ Do have faith in what you're doing.