Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring/DI: Constructor injection in child class

I've got a parent class with a constructor injected dependency:

class ParentClass {
  private final MyService service;

  @Autowired
  ParentClass(MyService service) {
    this.service=service;
  }
  // ...
}

If I inherit from this class, do I always need to redefine a constructor calling the parent constructor?

class ChildClass extends ParentClass {
  // Do I really need this?
  @Autowired
  ChildClass(MyService service) {
    super(service);
  }
  // ...
}

Using setter injection, I seem to be able to keep the dependency in the parent class and do not need to rewire it in the child, which sounds good to me if the child class does not touch the functionality linked to the dependency:

class ParentClass {
  private MyService service;

  @Autowired
  void setMyService(MyService service) {
    this.service=service;
  }
  // ...
}

class ChildClass extends ParentClass {
  // ...
}

It seems that if I want to avoid repeating the autowiring code and handling the dependency in the child, I can only do this using setter or field injection.

Is there a cleaner pattern to do this dependency injection or is this a case where field/setter injection has to be used, even though constructor injection is recommended?

Thanks!

like image 264
Alexander Hildenbrand Avatar asked Nov 15 '16 11:11

Alexander Hildenbrand


People also ask

When should we use constructor injection in Spring?

Use Constructor Injection when Object must be created with all of its dependency. P. S. - If you want to learn how to develop RESTful Web Service using Spring MVC in-depth, I suggest you join the REST with Spring certification class by Eugen Paraschiv. One of the best courses to learn REST with Spring MVC.

Which is better setter or constructor injection in Spring?

If there is only one property in a spring bean class then use constructor injection as constructor executes before methods constructor injection will be faster than setter injection.

Why is constructor injection better than Autowired?

Constructor injection makes code more robust. It allows us to create immutable objects, preventing NullPointerException s and other errors. You can find the code example on GitHub.

Can we use both constructor and setter injection?

Overriding: Setter injection overrides the constructor injection. If we use both constructor and setter injection, IOC container will use the setter injection. Changes: We can easily change the value by setter injection. It doesn't create a new bean instance always like constructor.


1 Answers

It's not a Spring issue, it's Java. Try removing child class constructor, and see what happens for yourself - your code shouldn't compile. See this answer, it was described before.

Answering your question on dependency injection, yes, @Autowired works for setter in the parent class, but as long as you don't override it in the subclass (give it a try). The reason is that Spring deals with objects, not classes, so when a subclass is instantiated Spring is not checking annotations on overridden methods in the parent class, unless annotation is marked as @Inherited (@Autowired is not).

So, you would either have to use @Autowired for each subclass (which I don't see as a big problem, actually), switch to setter injection, replace subclassing with delegation, or make parent class abstract and use constructor injection only in subclasses.

like image 133
borowis Avatar answered Sep 28 '22 17:09

borowis