Java无Spring Boot场景下手动依赖注入(DI)的判定及正确实现咨询
问题解答
1. 关于依赖注入(DI)的判定与调整方案
你的写法已经属于依赖注入的范畴,不存在因为写了new TalkingClockApplication(new TalkingClock())就不符合DI要求的问题。
DI的核心逻辑是「类的依赖不由自身内部创建,而是由外部传入」,你这里TalkingClockApplication需要的ConvertTime实现完全通过构造器参数从外部传入,没有在类内部自己newTalkingClock实例,已经满足DI的核心设计要求。
你写在main方法里的那行实例化代码属于依赖组装逻辑,没有任何问题:不管用不用容器,总要有一个入口位置负责所有依赖的创建和组装,这个位置叫「组合根」,main方法就是JavaSE场景下最常见的组合根。
如果不需要Spring Boot,想要更规范的DI实现,可以把依赖组装逻辑单独抽离统一管理,避免和业务逻辑耦合,示例如下:
// 统一管理所有依赖创建的容器类 public class SimpleAppContainer { // 统一提供ConvertTime实现,后续要换实现只改这里 public ConvertTime getConvertTime() { return new TalkingClock(); } // 统一提供TalkingClockApplication实例 public TalkingClockApplication getApp() { return new TalkingClockApplication(getConvertTime()); } }
调整后的main方法写法:
public static void main( String[] args ) throws Exception { SimpleAppContainer container = new SimpleAppContainer(); TalkingClockApplication aa = container.getApp(); // 原代码这里的strings应该是args,注意修正 int hours = Integer.parseInt(args[0]); int minutes = Integer.parseInt(args[1]); String friendlyText = aa.convertTime.convertTime(hours, minutes); System.out.println( friendlyText ); }
这种写法完全符合DI规范,所有业务类都不需要关心依赖的创建逻辑,切换实现只需要修改容器类即可。
2. 注释代码后空指针的原因
你注释掉new TalkingClockApplication(new TalkingClock());之后触发空指针,本质是convertTime属性没有被初始化赋值:
- 你的
TalkingClockApplication类没有给convertTime属性设置默认值,Java里引用类型成员变量默认值就是null - 注释掉那行代码后,要么你没有实例化
TalkingClockApplication就直接访问了成员变量convertTime,要么你实例化时没有调用带ConvertTime参数的构造器给convertTime赋值,自然调用的时候就会报空指针。
内容的提问来源于stack exchange,提问作者macaroni-chan
相关产品推荐
相关产品推荐

