@Autowired and Optional Dependencies

DZone 's Guide to

@Autowired and Optional Dependencies

Are your injected dependencies required or optional? What about all the permutations of possibilities?

· Java Zone ·
Free Resource
@Autowired annotation makes our lives easier. It also can result in a decreased amount of code if we are using it on properties of the class. We need neither constructors nor setter methods. It looks great at first glance, but the benefits rarely come without cost. Today I want to make you aware of the costs that have to be paid.


@Autowired annotation by default has an element "required" set to true, which means that the annotated dependency is required. However, we can turn off the default behavior and make the dependency optional as follows:
private Dependency dependency;
It can be useful, and since not all dependencies are always required, introducing this possibility was reasonable.

So what’s the problem with dependencies annotated in this way? Let’s look at the code:

class SomeClass {
 @Autowired private DependencyA dependencyA;
 @Autowired private DependencyB dependencyB;

 private DependencyC dependencyC;

 private DependencyD dependencyD;
We can create an instance of the SomeClass with following dependencies (all combinations are allowed):
  • DependencyA, DependencyB
  • DependencyA, DependencyB, DependencyC
  • DependencyA, DependencyB, DependencyD
  • DependencyA, DependencyB, DependencyC, DependencyD
And this is all great, but are you sure that all of those combinations are really useable and correct? What if the author of the class thought only about 1 and 4?

Optional Dependencies - Do it Right!

If we are considering an example presented in the previous paragraph, there are two possible answers to the following question:
  • All combinations are possible.
  • Only a subset of the combinations is possible.
In the case when all combinations are possible, I would leave the code as it is. If there is nothing that can go wrong and each state of the object is correct, then our code is descriptive enough. It clearly allows for anything so we can assume that anything that we will do will result in the creation of an object that we may work with.

What about the second point - a subset of the combinations? Let’s assume that only creating an object in either state 1 or state 4 is valid. Leaving the code as it is can result in the wrong usage of the object. We are allowing for the creation an object in invalid states (2 and 3). What can we do about this?

In that case, I think that we should drop @Autowired annotation. For the sake of the code readability and design quality it would be better to use constructors instead:

class SomeClass {
 private DependencyA dependencyA;
 private DependencyB dependencyB;
 private DependencyC dependencyC;
 private DependencyD dependencyD;

 public SomeClass(DependencyA dependencyA, DependencyB dependencyB) {
 this.dependencyA = dependencyA;
 this.dependencyB = dependencyB;

 public SomeClass(DependencyA dependencyA, DependencyB dependencyB, DependencyC dependencyC, DependencyD dependencyD) {
 this(dependencyA, dependencyB);
 this.dependencyC = dependencyC;
 this.dependencyD = dependencyD;

With this code, you know everything that is needed. You know what dependencies are required to create a correct object.

Stay Aware!

The article is not intended to convince you that it is better to not use @Autowired(required=false). Its purpose is to make you aware of the cost that you have to pay.

You have to protect your design, you have to protect object invariants and you should not allow for the existence of the objects in an invalid state. Of course, you may add a documentation or comment, but if we already have a semantic provided by the language which allows us to make it without additional effort we should use it.

dependency injection, java, spring

Published at DZone with permission of Sebastian Malaca , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}