use @autowired in abstract base class

后端 未结 5 1586
失恋的感觉
失恋的感觉 2021-02-05 13:12

As I know, field injection is not recommended. Should use constructor instead.

What I\'m trying to do here is using @Autowired in

相关标签:
5条回答
  • 2021-02-05 13:45

    I'd suggest using @Configuration classes. That way you can remove Spring annotations entirely from your business classes:

    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);
        }
    }
    

    With Configuration classes, you no longer rely on magical classpath scanning, but actually instantiate beans manually again. There's a lot less surprises in this approach.

    0 讨论(0)
  • 2021-02-05 13:53

    It works!!!! Constructor Autowired Qualifier Inheritance Injection

    Base abstract class DocumentoBase.

    @Qualifier("DocumentServiceBase")
    private DocumentService documentService;
    
    @Autowired
    public DocumentoBase(@Qualifier("DocumentServiceBase") DocumentService documentService){
        this.documentService = documentService;
    }
    

    Inherited class DocumentoController.

    @Qualifier("DocumentServiceImplv13")
    private DocumentService documentService;
    
    @Autowired
    public DocumentoController(@Qualifier("DocumentServiceImplv13") DocumentService documentService){
        super(documentService);
        this.documentService = documentService;
    }
    
    0 讨论(0)
  • 2021-02-05 14:00

    You can't do it like this with constructor injection, you will have to extend the subclass constructor with the dependencies of the Base class constructor, and call the correct super constructor (standard Java rules still apply, even if you use Spring).

    Field and Setter injection will do this correctly however.

    I would recommend Field injection in any case, as it reduces code duplication. Compare:

    class A {
        @Autowired private Field field;
    }
    

    Vs.

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

    In the constructor injection example you repeat yourself four times just to get a field set the way you want it... even though I love having things final, this kind of duplication just makes it hard to change code.

    0 讨论(0)
  • 2021-02-05 14:04

    The code that you provide won't compile. As long as in your base class you don't have the default constructor, you should call super(MyDemoService) in child.

    Inherited(sub) class:

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

    Or, if MySubService is an implementation of MyDemoService

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

    As long as your field MyDemoService myDemoService in abstract class is protected you can use it in subclasses.

    If you have multiple implementation of MyDemoService, than you have to use @Qualifier as described in the answer that you have mentioned.

    public Sub(@Qualifier("MySubService") MyDemoService mySubService){
        super(mySubService);
    }
    
    0 讨论(0)
  • 2021-02-05 14:05

    Don't use field injection, use constructor injection calling back to super constructors as appropriate.

    Constructor injection ensures your object is properly populated before instantiation, setter injection does not and makes code more bug prone (not another nullpointer bug....)

    If you are concerned about the extra code you have to write then use Project Lombok to let Lombok generate the constructor code for you as described here Why field injection is evil

    By the way as of Spring 4 if you only have a single constructor in your class you don't need @Autowired on the constructor.

    0 讨论(0)
提交回复
热议问题