ZEMOSO ENGINEERING STUDIO
May 1, 2021
5 min read

When not to @Autowire in Spring or Spring Boot applications

The above cartoon is a pretty common occurrence in most engineering and developer teams. Think about it this way: when we build products for our clients, we pay as much attention to what we should not be doing as we do to what we should be doing to create smart, future proofed products.

Besides, in most engineering problems, not paying attention to the “why” can lead to catastrophic codes.

But let’s get straight to the topic, dive deep into the different types of dependency injections for context before we discuss when and why we use one.

Types of dependency injection

1. Field injection

2. Constructor injection

3. Setter injection

Field injection

Simply put, spring will assign the dependencies directly to the fields, declaring a variable, hopefully private, and then annotating it with @Autowired.

Constructor injection

It’s when you statically define the list of required dependencies by articulating them to the class' constructor. You can let the spring container inject ‌dependencies directly through the constructor with @RestController.

Setter injection — rarely used

It is similar to field injection but the setter is annotated with @Autowired tag. It is the kind of injection where the spring framework uses the setter method to inject the dependency.

How do they differ?

 1. Field injection uses reflection to set the values of private variables.

 2. Constructor injection happens at the time of creating the object itself (and typically all the parameters are well-known).

 3. Setter injection uses setters to set the value.

Types of dependency injection

What’s the verdict?

Constructor injection is always the first choice when it comes to deploying a dependency injection because it’s reliable and strict.

Reliability: Constructor injection is the most reliable of the three because of immutable variables.

Maintainability: Constructor injection helps to identify the list of dependencies and makes the code more readable. In field and setter injections, autowired fields can mix up with regular fields, and therefore make it difficult to track the dependencies of the class. 

Testability: In construction injection, it is easy to mock dependencies as they can be passed and removed using the constructor, even without creating Spring Context that enables faster and cleaner tests. While using setter injection, it is easy to mock as mock objects can be set directly. However, it is most challenging to create mock beans for field injections as the shuffling between mock and actual beans is tedious. 

Consistency: Constructor injection is most consistent as the whole application uses similar coding and injection patterns. Setter and field injections are less consistent as they can be included anywhere in the code. 

Flexibility: Constructor offers the least amount of flexibility as it imposes strict design rules in the code. For setter and field injections, developers can easily add new dependencies, making them more flexible. 

Ease of code reviews: When you add a new dependency in constructor injection, developers have to update the constructors in multiple places so that reviewers can easily detect the breaking changes. When using field and setter injections, dependencies are added as a simple field, so reviewers might not even notice them. 

Modification of code: In setter and field injections, developers have the freedom to add unlimited new dependencies. Constructor injection is more aligned to the Open-Closed principle of SOLID principles. Any modification to the code for an extension or adding a new feature can be debated, which keeps the overall code cleaner. 

Cyclic dependency detection: Cyclic dependencies can be easily detected and fixed in constructor injection, while they are not detected at all in field and setter injections. 

Performance: For setter and field injections, each object can be created independently and dependencies are injected later on using reflection, thereby enabling faster launches. However, for constructor injection, beans have to be created in the correct order of dependencies, which increases the time taken to launch the application but ensures that developers have thought their structure through. 

Field injections are ideal for scenarios when constructor injection is absolutely unfeasible and circular dependencies have to be avoided, even if it is a work around. 

Other considerations

Somethings we consider when deciding between field injection and constructor injection are required and optional dependencies.

 1. While many argue that we can use field injection for optional and constructor injection for required dependencies, having optional dependency seems to be already reflective of bad design in most of the  cases; it might be worth taking another look at the design itself.

 2. Since the scope of an optional dependency is unrestricted, developers can add multiple dependencies by calling it optional, and reduce the quality @ of the overall code.

At Zemoso Labs, we follow the best design and coding principles, ensuring the highest quality of applications every time. This includes rigorous debate within our team members to identify the best possible solution. To learn more about our product engineering solutions, contact us today.

A version of this blog post was earlier published on Medium.

ZEMOSO ENGINEERING STUDIO

When not to @Autowire in Spring or Spring Boot applications

By Zemoso Engineering Studio
May 1, 2021
5 min read

The above cartoon is a pretty common occurrence in most engineering and developer teams. Think about it this way: when we build products for our clients, we pay as much attention to what we should not be doing as we do to what we should be doing to create smart, future proofed products.

Besides, in most engineering problems, not paying attention to the “why” can lead to catastrophic codes.

But let’s get straight to the topic, dive deep into the different types of dependency injections for context before we discuss when and why we use one.

Types of dependency injection

1. Field injection

2. Constructor injection

3. Setter injection

Field injection

Simply put, spring will assign the dependencies directly to the fields, declaring a variable, hopefully private, and then annotating it with @Autowired.

Constructor injection

It’s when you statically define the list of required dependencies by articulating them to the class' constructor. You can let the spring container inject ‌dependencies directly through the constructor with @RestController.

Setter injection — rarely used

It is similar to field injection but the setter is annotated with @Autowired tag. It is the kind of injection where the spring framework uses the setter method to inject the dependency.

How do they differ?

 1. Field injection uses reflection to set the values of private variables.

 2. Constructor injection happens at the time of creating the object itself (and typically all the parameters are well-known).

 3. Setter injection uses setters to set the value.

Types of dependency injection

What’s the verdict?

Constructor injection is always the first choice when it comes to deploying a dependency injection because it’s reliable and strict.

Reliability: Constructor injection is the most reliable of the three because of immutable variables.

Maintainability: Constructor injection helps to identify the list of dependencies and makes the code more readable. In field and setter injections, autowired fields can mix up with regular fields, and therefore make it difficult to track the dependencies of the class. 

Testability: In construction injection, it is easy to mock dependencies as they can be passed and removed using the constructor, even without creating Spring Context that enables faster and cleaner tests. While using setter injection, it is easy to mock as mock objects can be set directly. However, it is most challenging to create mock beans for field injections as the shuffling between mock and actual beans is tedious. 

Consistency: Constructor injection is most consistent as the whole application uses similar coding and injection patterns. Setter and field injections are less consistent as they can be included anywhere in the code. 

Flexibility: Constructor offers the least amount of flexibility as it imposes strict design rules in the code. For setter and field injections, developers can easily add new dependencies, making them more flexible. 

Ease of code reviews: When you add a new dependency in constructor injection, developers have to update the constructors in multiple places so that reviewers can easily detect the breaking changes. When using field and setter injections, dependencies are added as a simple field, so reviewers might not even notice them. 

Modification of code: In setter and field injections, developers have the freedom to add unlimited new dependencies. Constructor injection is more aligned to the Open-Closed principle of SOLID principles. Any modification to the code for an extension or adding a new feature can be debated, which keeps the overall code cleaner. 

Cyclic dependency detection: Cyclic dependencies can be easily detected and fixed in constructor injection, while they are not detected at all in field and setter injections. 

Performance: For setter and field injections, each object can be created independently and dependencies are injected later on using reflection, thereby enabling faster launches. However, for constructor injection, beans have to be created in the correct order of dependencies, which increases the time taken to launch the application but ensures that developers have thought their structure through. 

Field injections are ideal for scenarios when constructor injection is absolutely unfeasible and circular dependencies have to be avoided, even if it is a work around. 

Other considerations

Somethings we consider when deciding between field injection and constructor injection are required and optional dependencies.

 1. While many argue that we can use field injection for optional and constructor injection for required dependencies, having optional dependency seems to be already reflective of bad design in most of the  cases; it might be worth taking another look at the design itself.

 2. Since the scope of an optional dependency is unrestricted, developers can add multiple dependencies by calling it optional, and reduce the quality @ of the overall code.

At Zemoso Labs, we follow the best design and coding principles, ensuring the highest quality of applications every time. This includes rigorous debate within our team members to identify the best possible solution. To learn more about our product engineering solutions, contact us today.

A version of this blog post was earlier published on Medium.

Recent Publications
Actual access control without getting in the way of actual work: 2023
Actual access control without getting in the way of actual work: 2023
March 13, 2023
Breaking the time barrier: Test Automation and its impact on product launch cycles
Breaking the time barrier: Test Automation and its impact on product launch cycles
January 20, 2023
Product innovation for today and the future! It’s outcome-first, timeboxed, and accountable
Product innovation for today and the future! It’s outcome-first, timeboxed, and accountable
January 9, 2023
From "great potential" purgatory to "actual usage" reality: getting SDKs right in a product-led world
From "great potential" purgatory to "actual usage" reality: getting SDKs right in a product-led world
December 6, 2022
Why Realm trumps SQLite as database of choice for complex mobile apps — Part 2
Why Realm trumps SQLite as database of choice for complex mobile apps — Part 2
October 13, 2022
Testing what doesn’t exist with a Wizard of Oz twist
Testing what doesn’t exist with a Wizard of Oz twist
October 12, 2022
Docs, Guides, Resources: Getting developer microsites right in a product-led world
Docs, Guides, Resources: Getting developer microsites right in a product-led world
September 20, 2022
Beyond methodologies: Five engineering do's for an agile product build
Beyond methodologies: Five engineering do's for an agile product build
September 5, 2022
Actual access control without getting in the way of actual work: 2023
Actual access control without getting in the way of actual work: 2023
March 13, 2023
Breaking the time barrier: Test Automation and its impact on product launch cycles
Breaking the time barrier: Test Automation and its impact on product launch cycles
January 20, 2023
Product innovation for today and the future! It’s outcome-first, timeboxed, and accountable
Product innovation for today and the future! It’s outcome-first, timeboxed, and accountable
January 9, 2023
From "great potential" purgatory to "actual usage" reality: getting SDKs right in a product-led world
From "great potential" purgatory to "actual usage" reality: getting SDKs right in a product-led world
December 6, 2022
Why Realm trumps SQLite as database of choice for complex mobile apps — Part 2
Why Realm trumps SQLite as database of choice for complex mobile apps — Part 2
October 13, 2022
ZEMOSO ENGINEERING STUDIO
May 1, 2021
5 min read

When not to @Autowire in Spring or Spring Boot applications

The above cartoon is a pretty common occurrence in most engineering and developer teams. Think about it this way: when we build products for our clients, we pay as much attention to what we should not be doing as we do to what we should be doing to create smart, future proofed products.

Besides, in most engineering problems, not paying attention to the “why” can lead to catastrophic codes.

But let’s get straight to the topic, dive deep into the different types of dependency injections for context before we discuss when and why we use one.

Types of dependency injection

1. Field injection

2. Constructor injection

3. Setter injection

Field injection

Simply put, spring will assign the dependencies directly to the fields, declaring a variable, hopefully private, and then annotating it with @Autowired.

Constructor injection

It’s when you statically define the list of required dependencies by articulating them to the class' constructor. You can let the spring container inject ‌dependencies directly through the constructor with @RestController.

Setter injection — rarely used

It is similar to field injection but the setter is annotated with @Autowired tag. It is the kind of injection where the spring framework uses the setter method to inject the dependency.

How do they differ?

 1. Field injection uses reflection to set the values of private variables.

 2. Constructor injection happens at the time of creating the object itself (and typically all the parameters are well-known).

 3. Setter injection uses setters to set the value.

Types of dependency injection

What’s the verdict?

Constructor injection is always the first choice when it comes to deploying a dependency injection because it’s reliable and strict.

Reliability: Constructor injection is the most reliable of the three because of immutable variables.

Maintainability: Constructor injection helps to identify the list of dependencies and makes the code more readable. In field and setter injections, autowired fields can mix up with regular fields, and therefore make it difficult to track the dependencies of the class. 

Testability: In construction injection, it is easy to mock dependencies as they can be passed and removed using the constructor, even without creating Spring Context that enables faster and cleaner tests. While using setter injection, it is easy to mock as mock objects can be set directly. However, it is most challenging to create mock beans for field injections as the shuffling between mock and actual beans is tedious. 

Consistency: Constructor injection is most consistent as the whole application uses similar coding and injection patterns. Setter and field injections are less consistent as they can be included anywhere in the code. 

Flexibility: Constructor offers the least amount of flexibility as it imposes strict design rules in the code. For setter and field injections, developers can easily add new dependencies, making them more flexible. 

Ease of code reviews: When you add a new dependency in constructor injection, developers have to update the constructors in multiple places so that reviewers can easily detect the breaking changes. When using field and setter injections, dependencies are added as a simple field, so reviewers might not even notice them. 

Modification of code: In setter and field injections, developers have the freedom to add unlimited new dependencies. Constructor injection is more aligned to the Open-Closed principle of SOLID principles. Any modification to the code for an extension or adding a new feature can be debated, which keeps the overall code cleaner. 

Cyclic dependency detection: Cyclic dependencies can be easily detected and fixed in constructor injection, while they are not detected at all in field and setter injections. 

Performance: For setter and field injections, each object can be created independently and dependencies are injected later on using reflection, thereby enabling faster launches. However, for constructor injection, beans have to be created in the correct order of dependencies, which increases the time taken to launch the application but ensures that developers have thought their structure through. 

Field injections are ideal for scenarios when constructor injection is absolutely unfeasible and circular dependencies have to be avoided, even if it is a work around. 

Other considerations

Somethings we consider when deciding between field injection and constructor injection are required and optional dependencies.

 1. While many argue that we can use field injection for optional and constructor injection for required dependencies, having optional dependency seems to be already reflective of bad design in most of the  cases; it might be worth taking another look at the design itself.

 2. Since the scope of an optional dependency is unrestricted, developers can add multiple dependencies by calling it optional, and reduce the quality @ of the overall code.

At Zemoso Labs, we follow the best design and coding principles, ensuring the highest quality of applications every time. This includes rigorous debate within our team members to identify the best possible solution. To learn more about our product engineering solutions, contact us today.

A version of this blog post was earlier published on Medium.

Recent Publications

ZEMOSO ENGINEERING STUDIO

Testing what doesn’t exist with a Wizard of Oz twist

October 12, 2022
7 min read
ZEMOSO ENGINEERING STUDIO

Beyond methodologies: Five engineering do's for an agile product build

September 5, 2022
6 min read
ZEMOSO ENGINEERING STUDIO

How we built a big data platform for a futuristic AgriTech product

June 3, 2022
8 min read
ZEMOSO NEWS

Zemoso Labs starts operations in Waterloo, Canada

May 25, 2022
5 min read
ZEMOSO ENGINEERING STUDIO

Honorable mention at O’Reilly’s Architectural Katas event

May 17, 2021
5 min read
ZEMOSO ENGINEERING STUDIO

Product dev with testable spring boot applications, from day one

May 4, 2021
5 min read
ZEMOSO ENGINEERING STUDIO

Efficiently handle data and integrations in Spring Boot

January 24, 2021
5 min read
ZEMOSO ENGINEERING STUDIO

Our favorite CI/CD DevOps Practice: Simplify with GitHub Actions

October 25, 2020
5 min read
ZEMOSO ENGINEERING STUDIO

How to use BERT and DNN to build smarter NLP algorithms for products

February 14, 2020
12 min read
ZEMOSO ENGINEERING STUDIO

GraphQL — Why is it essential for agile product development?

April 30, 2019
12 min read
ZEMOSO ENGINEERING STUDIO

GraphQL with Java Spring Boot and Apollo Angular for Agile platforms

April 30, 2019
9 min read
ZEMOSO ENGINEERING STUDIO

Deploying Airflow on Kubernetes 

November 30, 2018
2 min read
ZEMOSO PRODUCT STUDIO

How to validate your Innovation: Mastering Experiment Design

November 22, 2018
8 min read
ZEMOSO PRODUCT STUDIO

Working Backwards: Amazon's Culture of Innovation: My notes

November 19, 2018
8 min read
ZEMOSO ENGINEERING STUDIO

Product developer POV: Caveats when building with Spark

November 5, 2018
2 min read

Want more best practices?

Access thought-leadership and best practice content across
the product development lifecycle

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

© 2023  Zemoso Technologies
Privacy Policy

Terms of Use
LinkedIn Page - Zemoso TechnologiesFacebook Page - Zemoso TechnologiesTwitter Account - Zemoso Technologies

© 2021 Zemoso Technologies
Privacy Policy

LinkedIn Page - Zemoso TechnologiesFacebook Page - Zemoso TechnologiesTwitter Account - Zemoso Technologies
May 25, 2023