Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring @Autowire on Properties vs Constructor

People also ask

Can we use @autowired for constructor?

In Spring, you can use @Autowired annotation to auto-wire bean on the setter method, constructor , or a field . Moreover, it can autowire the property in a particular bean. We must first enable the annotation using below configuration in the configuration file. We have enabled annotation 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.

What is difference between Autowired and constructor injection?

These are mentioned on the above links. By constructor means to not annotate the class properties but the constructor arguments. Auto detect is like scanning where Spring will work out bean candidates. So, autowiring by constructor is a way of implementing constructor based injection.

Which one is better constructor or setter injection?

Setter Injection has upper hand over Constructor Injection in terms of readability. Since for configuring Spring we use XML files, readability is a much bigger concern.


Yes, option B (which is called constructor injection) is actually recommended over field injection, and has several advantages:

  • the dependencies are clearly identified. There is no way to forget one when testing, or instantiating the object in any other circumstance (like creating the bean instance explicitly in a config class)
  • the dependencies can be final, which helps with robustness and thread-safety
  • you don't need reflection to set the dependencies. InjectMocks is still usable, but not necessary. You can just create mocks by yourself and inject them by simply calling the constructor

See this blog post for a more detailed article, by one of the Spring contributors, Olivier Gierke.


I will explain you in simple words:

In Option(A), you are allowing anyone (in different class outside/inside the Spring container) to create an instance using default constructor (like new SomeService()), which is NOT good as you need SomeOtherService object (as a dependency) for your SomeService.

Is there anything else the autowired constructor does besides add code to the unit tests? Is this a more preferred way to do dependency injection?

Option(B) is preferred approach as it does NOT allow to create SomeService object without actually resolving the SomeOtherService dependency.


Please note, that since Spring 4.3 you don't even need an @Autowired on your constructor, so you can write your code in Java style rather than tying to Spring's annotations. Your snippet would look like that:

@Component
public class SomeService {
    private final SomeOtherService someOtherService;

    public SomeService(SomeOtherService someOtherService){
        this.someOtherService = someOtherService;
    }
}

Good to know

If there is only one constructor call, there is no need to include an @Autowired annotation. Then you can use something like this:

@RestController
public class NiceController {

    private final DataRepository repository;

    public NiceController(ChapterRepository repository) {
        this.repository = repository;
    }
}

... example of Spring Data Repository injection.


Actually, In my experience, The second option is better. Without the need for @Autowired. In fact, it is wiser to create code that is not too tightly coupled with the framework (as good as Spring is). You want code that tries as much as possible to adopt a deferred decision-making approach. That is as much pojo as possible, so much such that the framework can be swapped out easily. So I would advise you create a separate Config file and define your bean there, like this:

In SomeService.java file:

public class SomeService {
    private final SomeOtherService someOtherService;

    public SomeService(SomeOtherService someOtherService){
        this.someOtherService = someOtherService;
    }
}

In ServiceConfig.java file:

@Config
public class ServiceConfig {
    @Bean
    public SomeService someService(SomeOtherService someOtherService){
        return new SomeService(someOtherService);
    }
}

In fact, if you want to get deeply technical about it, there are thread safety questions (among other things) that arise with the use of Field Injection (@Autowired), depending on the size of the project obviously. Check this out to learn more on the advantages and disadvantages of Autowiring. Actually, the pivotal guys actually recommend that you use Constructor injection instead of Field Injection