4
\$\begingroup\$

I'm six months into a Java training program and have developed a Spring Boot application, adhering to Java's separation of concerns principle. I've organized my application with distinct sections for data logic, input data, and business logic. Now, I'm seeking guidance specifically on the choice between Field Injections and Constructor Injections in my design. Which approach is recommended for achieving a modular and maintainable design in Java applications? What are the best practices and considerations for using either Field or Constructor Injections? Thank you for your insights! (see example of a class below)

@Service
public class NewsletterService {


    @Qualifier("gameIO")
    @Autowired
    IO io;

    @Autowired
    NewsLetterRepo newsLetterRepo;
    @Autowired
    Menu menu;

    @Autowired
    StatusService statusService;

    public void createNewsLetter(Player activePlayer) {
        NewsLetter newsLetter = new NewsLetter();
        if (activePlayer.getRole().equals(Role.admin)){
            if (statusService.getStatus().equals(Status.SVENSKA)){
                System.out.println(io.getInGameMessages().get(1));
            } else if (statusService.getStatus().equals(Status.ENGLISH)){
                System.out.println(io.getInGameMessages().get(2));
            }
            String getContent = io.inputUserString();
            newsLetter.setContent(getContent);
            newsLetter.setPublishDateTime(LocalDateTime.now());
            newsLetterRepo.save(newsLetter);
        } else {
            if ((statusService.getStatus().equals(Status.SVENSKA))){
                System.out.println(io.getInGameMessages().get(3));
            } else if (statusService.getStatus().equals(Status.ENGLISH)){
                System.out.println(io.getInGameMessages().get(4));
            }
        }
    }

    public void displayNewsletters(){
        System.out.println(newsLetterRepo.findAll());
    }

}
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

You can refer to the official documentation of Spring, section "Constructor-based or setter-based DI?", it says"

Since you can mix constructor-based and setter-based DI, it is a good rule of thumb to use constructors for mandatory dependencies and setter methods or configuration methods for optional dependencies. Note that use of the @Autowired annotation on a setter method can be used to make the property be a required dependency; however, constructor injection with programmatic validation of arguments is preferable.

The Spring team generally advocates constructor injection, as it lets you implement application components as immutable objects and ensures that required dependencies are not null. Furthermore, constructor-injected components are always returned to the client (calling) code in a fully initialized state. As a side note, a large number of constructor arguments is a bad code smell, implying that the class likely has too many responsibilities and should be refactored to better address proper separation of concerns.

Setter injection should primarily only be used for optional dependencies that can be assigned reasonable default values within the class. Otherwise, not-null checks must be performed everywhere the code uses the dependency. One benefit of setter injection is that setter methods make objects of that class amenable to reconfiguration or re-injection later. Management through JMX MBeans is therefore a compelling use case for setter injection.

Use the DI style that makes the most sense for a particular class. Sometimes, when dealing with third-party classes for which you do not have the source, the choice is made for you. For example, if a third-party class does not expose any setter methods, then constructor injection may be the only available form of DI.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Thanks for copy-pasting that. We explicitly use field injection in my current work and it absolutely leads to monolithic god-classes. Of course and unfortunately, we also use Lombok so even if we preferred constructor injection the code smell outlined by the Spring team would be hidden in the auto-generated constructors... Lombok, in my opinion, is one of the worst things to get a foothold in the Java development ecosystem. \$\endgroup\$ Mar 6 at 6:44
1
\$\begingroup\$

First, I don't know Spring and I'm proud, so there may be some Spring-specific reasons to chose one of these styles, that I'm not aware of.
In terms of pure dependency injection however, usually constructors are a better choice, as this way your components remain more abstract from the point of view of dependency-injection framework. That is, when using field/setter injection, the framework needs to analyse in detail full structure of your components (using reflection) to find all fields/setters it needs to inject (in case of constructor injection it only needs to get the param list of a given constructor).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.