在抽象基类中使用@autowired

据我所知,不建议进行field injection 。 应该使用constructor

我在这里尝试做的是在基类的构造函数中使用@Autowired ,并使其可供所有子类访问。 在某些子类中,我还需要一些特定的bean来从它们的构造函数中@Autowired 。 演示代码如下:

基类:

 public abstract class Base { protected final MyDemoService myDemoService; @Autowired public Base(MyDemoService myDemoService) { this.myDemoService = myDemoService; } } 

inheritance(子)类:

 public class Sub extends Base { private final MySubService mySubService; @Autowired public Sub(MySubService mySubService) { this.mySubService = mySubService; } } 

这将给我一个’无默认构造函数’错误。
它类似于问题: 类似的问题和答案 ,但它在这里不起作用。


我已经潜入了一段时间,我发现这篇关于dependency injection文章: 进一步阅读

我认为Setter Injection是我问题的正确方法吗?

塞特犬注射:

 public abstract class Base { protected MyDemoService myDemoService; @Autowired public void setMyDemoService(MyDemoService myDemoService) { this.myDemoService = myDemoService; } } 

我是Java Spring Boot的新手,想要从你们那里获得一些专业知识。 任何讨论都将受到高度赞赏!

您提供的代码将无法编译。 只要在您的基类中没有默认构造函数,就应该在子级中调用super(MyDemoService)

inheritance(子)类:

 public class Sub extends Base { private final MySubService mySubService; @Autowired public Sub(MySubService mySubService, MyDemoService myDemoService){ super(myDemoService); this.mySubService = mySubService; } } 

或者,如果MySubServiceMySubService的实现

 @Autowired public Sub(MySubService mySubService){ super(mySubService); } 

只要抽象类中的字段MyDemoService myDemoService protected您就可以在子类中使用它。

如果您有多个MyDemoService实现, MyDemoService您必须使用@Qualifier ,如您提到的答案中所述 。

 public Sub(@Qualifier("MySubService") MyDemoService mySubService){ super(mySubService); } 

不要使用字段注入,使用构造函数注入调用适当的超级构造函数。

构造函数注入确保在实例化之前正确填充对象,setter注入不会使代码更容易出错(不是另一个nullpointer bug ….)

如果你担心你必须编写的额外代码,那么使用Project Lombok让Lombok为你生成构造函数代码,如下所述为什么字段注入是邪恶的

从Spring 4开始,如果你的类中只有一个构造函数,那么构造函数中不需要@Autowired。

我建议使用@Configuration类。 这样您就可以完全从业务类中删除Spring注释:

 public class Sub extends Base { private final MySubService mySubService; public Sub(MySubService mySubService, MyDemoService myDemoService){ super(myDemoService); this.mySubService = mySubService; } } 

Spring配置:

 @Configuration public class SubConfig{ @Bean public Sub sub(MySubService subService, MyDemoService demoService){ return new Sub(subService, demoService); } } 

使用Configuration类,您不再依赖于神奇的类路径扫描,而是再次手动实例化bean。 这种方法的惊喜要少得多。

你不能用构造函数注入这样做,你必须使用Base类构造函数的依赖项扩展子类构造函数,并调用正确的super构造函数(标准Java规则仍然适用,即使你使用Spring)。

然而,Field和Setter注入将正确地执行此操作。

在任何情况下我都会建议使用Field注入,因为它可以减少代码重复。 相比:

 class A { @Autowired private Field field; } 

比。

 class A { private final Field field; /** plus mandatory javadocs */ @Autowired public A(Field field) { this.field = field; } } 

在构造函数注入示例中,您重复自己四次只是为了让字段按照您想要的方式设置…即使我喜欢最终的事情,这种重复只会让代码变得难以改变。