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

2023-08-02 14:12:55 +08:00
 csw3983931

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

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

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

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

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

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

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

© 2021 V2EX