在抽象基类中使用@autowired

时间:2017-03-10 08:37:43

标签: java spring spring-boot javabeans

据我所知,不推荐使用field injection。应改为使用constructor

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

基类:

public abstract class Base {

    protected final MyDemoService myDemoService;

    @Autowired
    public Base(MyDemoService myDemoService) {
        this.myDemoService = myDemoService;
    }
}

继承(子)类:

public class Sub extends Base {

    private final MySubService mySubService;

    @Autowired
    public Sub(MySubService mySubService) {
        this.mySubService = mySubService;
    }
} 

这会给我一个没有默认构造函数'错误。
它类似于问题similar question and answer,但它在这里不起作用。

我已经潜入了一段时间,我发现这篇文章关于dependency injectionfurther read

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

二传手注射:

public abstract class Base {

    protected MyDemoService myDemoService;

    @Autowired
    public void setMyDemoService(MyDemoService myDemoService) {
        this.myDemoService = myDemoService;
    }
}

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

5 个答案:

答案 0 :(得分:3)

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

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

如果您担心必须编写的额外代码,请使用Project Lombok让Lombok为您生成构造函数代码,如此处所述Why field injection is evil

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

答案 1 :(得分:3)

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

继承(子)类:

public class Sub extends Base {

    private final MySubService mySubService;

    @Autowired
    public Sub(MySubService mySubService, MyDemoService myDemoService){
        super(myDemoService);
        this.mySubService = mySubService;
    }
} 

或者,如果MySubServiceMyDemoService

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

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

如果您有MyDemoService的多个实施,则必须使用answer that you have mentioned中所述的@Qualifier

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

答案 2 :(得分:2)

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

public class Sub extends Base {

    private final MySubService mySubService;

    public Sub(MySubService mySubService, MyDemoService myDemoService){
        super(myDemoService);
        this.mySubService = mySubService;
    }
} 

Spring config:

@Configuration
public class SubConfig{

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

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

答案 3 :(得分:1)

有效!!!!构造函数自动连接的限定符继承注入

基础抽象类DocumentoBase。

sleep(1)

继承的类DocumentoController。

didSet

答案 4 :(得分:-2)

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

Field和Setter注入会正确地执行此操作。

我建议在任何情况下使用Field注入,因为它减少了代码重复。比较:

class A {
    @Autowired private Field field;
}

Vs以上。

class A {
    private final Field field;

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

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