Java:仅在父类构造器注入Bean,不使用字段注入的设计疑问
解决方案:将父类依赖改为构造器注入
要实现仅在父类构造器中注入所有Bean、移除字段级@Inject的需求,我们只需要调整父类的构造器设计,并让子类正确传递依赖即可。下面是具体的实现步骤和代码示例:
1. 修改父类A:构造器注入所有依赖
首先,把父类中原本用字段注入的Param2移到构造器参数中,同时保留Param1的构造器注入,这样父类的所有依赖都通过构造器传入,确保依赖清晰且不可变:
public abstract class A implements SomeFrameworkInterface { private final Param1 a1; private final Param2 a2; // 移除字段上的@Inject // 构造器接收所有依赖,protected修饰确保子类可访问 protected A(Param1 a1, Param2 a2) { this.a1 = a1; this.a2 = a2; } @Override public void someFrameworkInterfaceMethod() { // 原有逻辑保持不变 doMyStuff(); } protected abstract void doMyStuff(); }
2. 修改子类B:传递父类所需依赖
子类需要在自己的构造器中接收父类构造器需要的所有参数,然后通过super()调用父类构造器传递这些依赖。同时子类的构造器需要加上@Inject,让DI框架(比如Spring/Guice)能够解析并注入对应的Bean实例:
@Named @SomeCustomAnnotation(property="someProperty") public class B extends A { // 子类构造器注入所有父类需要的依赖 @Inject public B(Param1 b1, Param2 b2) { super(b1, b2); // 调用父类构造器传递参数 // 子类自身的初始化逻辑可以在这里添加 } @Override protected void doMyStuff() { // 子类的业务逻辑实现 } }
关键说明
- 构造器注入的优势:这种方式符合依赖注入的最佳实践——依赖关系清晰可见、实例不可变(用
final修饰字段)、单元测试时可以轻松手动传入模拟对象。 - 子类构造器的
@Inject:因为DI框架最终需要实例化的是子类B,所以必须在子类的构造器上添加@Inject(如果子类只有这一个构造器,Spring 4.3+可以省略@Inject,但显式添加会让代码更清晰)。 - 限定符的使用:如果
Param1或Param2存在多个Bean实例,可以在构造器参数上添加@Named或自定义限定符注解,比如@Inject public B(@Named("specificParam1") Param1 b1, Param2 b2),确保框架注入正确的实例。
内容的提问来源于stack exchange,提问作者softwareRat
相关产品推荐
相关产品推荐

