依赖注入(di)是spring boot解耦核心,通过接口定义契约、@autowired自动装配、跨模块接口调用及spring event异步通知实现松耦合。

依赖注入(DI)是 Spring Boot 实现业务解耦最直接、最常用的方式。它把对象的创建和依赖关系交给 Spring 容器管理,让业务类只关注自身逻辑,不操心“谁来提供我需要的服务”。
用接口定义契约,而不是依赖具体实现
比如订单服务需要发短信,不要在 Service 里 new SmsUtil(),而是定义一个接口:
- SmsService:声明 send(String phone, String content) 方法
- SmsServiceImpl:实现该接口,内部调用第三方 SDK
- 业务 Service(如 OrderService)只持有 SmsService 类型字段,不关心它是哪个实现
这样后续换成邮件通知、站内信,或测试时用 MockSmsService,都不用改 OrderService 的代码。
用 @Autowired 自动装配,避免手动 new
Spring 启动时会扫描所有加了 @Service、@Component 等注解的类,注册为 Bean。你在使用处标注 @Autowired,容器就自动把匹配类型的 Bean 塞进来:
- 字段注入:简单直接,适合大多数场景(注意不可用于构造阶段校验)
- 构造函数注入:更推荐,能保证依赖不为空,且利于单元测试
- Setter 注入:较少用,适用于可选依赖或后期重置场景
只要类型匹配,Spring 就能完成注入;有多个实现时,用 @Qualifier 指定 Bean 名称即可。
把跨模块调用变成接口调用
像 ERP 和 TMS 模块之间需要共享订单数据,不能让 tms 直接依赖 erp 的 DAO 层——这会造成模块紧耦合甚至循环依赖。正确做法是:
- tms 模块定义一个 ErpOrderAccessor 接口(只声明要什么数据)
- erp 模块提供 ErpOrderAccessorImpl,并用 @Service 注册为 Bean
- tms 中通过 @Autowired 注入 ErpOrderAccessor,完全不知道底层是 JDBC 还是 Feign 调用
接口定义在调用方,实现放在被调用方,依赖方向清晰,编译期就隔离了模块。
配合 Spring Event 做异步解耦
不是所有业务都得同步完成。比如下单成功后要发优惠券、更新积分、推送消息——这些可以抽成独立事件监听器:
- OrderService 发布 OrderPaidEvent
- CouponService、PointService、NotifyService 分别监听该事件,各自处理
- 主流程不等待子任务,失败也不影响下单结果
这种方式把强依赖变成松散的“通知-响应”关系,既保持业务完整性,又降低耦合度和响应延迟。











