Spring's Annotation Type Required deprecation

There are three ways to inject a bean via annotation:

Field injection

@Autowired
private FooService fooService;

Setter injection

private FooService fooService;

@Autowired
public void setFooService(FooService fooService) {
    this.fooService = fooService
}

Constructor injection (this is the mentioned replacement)

private final FooService fooService;

@Autowired
public MyComponent(FooService fooService) {
    this.fooService = fooService;
}

As you can see, the only way to declare your Service final is by using the constructor injection, which replaces the @Required annotation because it forces the user of your class to instantiate it with the required services. The user does not have to be Spring, it could be a simple unit test as well.

You should use constructor injection for mandatory dependencies and setter injections for optional dependencies instead of field injection. Some reasons why:

  • It makes it clear to everybody which dependencies are required
  • It makes testing easier
  • You can make your objects immutable

Further reading:

  • http://olivergierke.de/2013/11/why-field-injection-is-evil/
  • https://www.vojtechruzicka.com/field-dependency-injection-considered-harmful/
  • https://spring.io/blog/2007/07/11/setter-injection-versus-constructor-injection-and-the-use-of-required/

Update: non-annotated constructor injection

As one commentator was wondering about a final field annotated with @Autowired while the constructor was not annotated:

If a class only declares a single constructor to begin with, it will always be used, even if not annotated.

https://docs.spring.io/spring-framework/docs/5.2.5.RELEASE/javadoc-api/org/springframework/beans/factory/annotation/Autowired.html ("Autowired Constructors")

But even though it is not necessary to annotate the constructor in this case, I would still do it: it documents the code and if anyone will ever add another (non-annotated) constructor, the code will still work.