依赖注入场景下,如何让中间类获取注入对象传递给父类构造器?
方案1:显式注入ElectricEngine到ElectricVehicle构造器,利用DI框架自动传递
让ElectricVehicle的构造器依赖注入ElectricEngine,子类Tesla仅需传递转向系统参数,DI框架会自动为父类提供ElectricEngine的单例实例。
class ElectricVehicle extends Vehicle { // 注入Singleton的ElectricEngine,DI框架自动处理实例获取 @Inject ElectricVehicle(ElectricEngine engine, SteeringSystem ss) { super(engine, ss); } } class Tesla extends ElectricVehicle { @Inject Tesla(ElectricEngine engine, SteerByWireSystem ss) { super(engine, ss); } }
虽然Tesla构造器仍需声明ElectricEngine参数,但这是Java构造器调用规则的要求——子类必须显式传递父类构造器所需参数。实际使用中,DI框架会自动注入ElectricEngine的单例实例,你无需手动创建或传递,Tesla代码也无需关心ElectricEngine的具体实现细节。
方案2:使用静态工厂类封装ElectricEngine的获取
创建单例工厂类,由DI框架注入ElectricEngine实例,ElectricVehicle通过工厂获取实例并传递给父类。
// 工厂类,由DI注入初始化实例 class EngineFactory { private static ElectricEngine electricEngineInstance; @Inject EngineFactory(ElectricEngine engine) { electricEngineInstance = engine; } public static ElectricEngine getElectricEngine() { return electricEngineInstance; } } class ElectricVehicle extends Vehicle { ElectricVehicle(SteeringSystem ss) { super(EngineFactory.getElectricEngine(), ss); } } class Tesla extends ElectricVehicle { @Inject Tesla(SteerByWireSystem ss) { super(ss); } }
这种方式让Tesla完全无需关心Engine相关参数,ElectricVehicle通过工厂获取预初始化的ElectricEngine单例。需注意必须确保EngineFactory在ElectricVehicle实例化前被DI框架初始化,避免空指针异常。
方案3:利用DI框架的辅助注入(如Dagger的@AssistedInject)
如果使用Dagger这类支持辅助注入的框架,可通过@AssistedInject分离手动传递的参数(如转向系统)和DI自动注入的参数(如Engine)。
class ElectricVehicle extends Vehicle { @AssistedInject ElectricVehicle(ElectricEngine engine, @Assisted SteeringSystem ss) { super(engine, ss); } // 定义辅助工厂接口,用于创建实例 @AssistedFactory interface Factory { ElectricVehicle create(SteeringSystem ss); } } class Tesla extends ElectricVehicle { @AssistedInject Tesla(ElectricEngine engine, @Assisted SteerByWireSystem ss) { super(engine, ss); } @AssistedFactory interface Factory { Tesla create(SteerByWireSystem ss); } }
使用时只需注入Tesla.Factory,调用create(steerByWireSystem)即可创建Tesla实例——ElectricEngine由DI框架自动注入,无需在Tesla代码中显式声明或传递,完美满足“底层子类无需指定Engine类型”的需求。
方案4:抽象类+构造器约束
将ElectricVehicle设为抽象类,强制子类通过DI注入ElectricEngine,同时通过构造器封装隐藏细节:
abstract class ElectricVehicle extends Vehicle { protected ElectricVehicle(ElectricEngine engine, SteeringSystem ss) { super(engine, ss); } } class Tesla extends ElectricVehicle { @Inject Tesla(ElectricEngine engine, SteerByWireSystem ss) { super(engine, ss); } }
这种方式通过抽象类明确ElectricVehicle家族必须使用ElectricEngine,Tesla构造器虽仍需声明ElectricEngine参数,但DI框架会自动处理注入,且Tesla无需关心Engine的具体实现逻辑。
内容的提问来源于stack exchange,提问作者kane

