DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Smart Dependency Injection With Spring: Assignability (Part 2 of 3)
  • Smart Dependency Injection With Spring: Overview (Part 1 of 3)
  • Smart Dependency Injection With Spring - Generics (Part 3/3)
  • Introduction to Apache Kafka With Spring

Trending

  • Mastering Advanced Aggregations in Spark SQL
  • Developers Beware: Slopsquatting and Vibe Coding Can Increase Risk of AI-Powered Attacks
  • Memory Leak Due to Time-Taking finalize() Method
  • AWS to Azure Migration: A Cloudy Journey of Challenges and Triumphs
  1. DZone
  2. Coding
  3. Frameworks
  4. Best Practices for Dependency Injection With Spring

Best Practices for Dependency Injection With Spring

Learn how to use Project Lombok when adopting dependency injection using the Spring Framework.

By 
John Thompson user avatar
John Thompson
·
Dec. 19, 19 · Presentation
Likes (17)
Comment
Save
Tweet
Share
40.6K Views

Join the DZone community and get the full member experience.

Join For Free

two leaves in vase

Learn how to use Project Lombok when adopting dependency injection using the Spring Framework.


In this post, I’m going to show you how to use Project Lombok for best practices in dependency injection with the Spring Framework.

The Spring Framework itself has a variety of different ways we can perform dependency injection. The flexibility of options is a strength of the Spring Framework. However, not all of the dependency injection options are considered best practices. Some are actually very poor.

You may also like:  How Dependency Injection (DI) Works in Spring Java Application Development

Dependency Injection Examples

I’ve set up examples for us to review the different dependency injection options we have to work with.

Let’s use an example Spring Service. For our purposes, the service has one method that returns a string.  We’ll take our ‘service’ and use Spring to inject it into some faux controllers. Keep in mind, we’re just exploring how we can do dependency injection with the Spring Framework.

Example Service

Java
 




xxxxxxxxxx
1


 
1
@Service
2
public class MyService {
3
    public String getHello(){
4
        return "Hello";
5
    }
6
}



Our field controller has one public property for the service. We can annotate this field, and Spring will inject an instance of the service.

Property Injection

Field Controller

Java
 




xxxxxxxxxx
1


 
1
@Controller
2
public class FieldController {
3
    @Autowired
4
    MyService myService;
5
    public String saySomething(){
6
        return myService.getHello();
7
    }
8

          
9
}



This is just a public property and does not have a setter. Clearly, this is not a good practice. Nor is it recommended.

We can improve on this slightly, and make the access to the field private. The Spring Framework does allow you to autowire private fields. You do see people doing this. And Spring will perform some reflection magic to perform dependency injection.

Private Field Controller

Java
 




xxxxxxxxxx
1


 
1
@Controller 
2
public class PrivateFieldController {
3
    @Autowired
4
    private MyService myService;
5
    public String saySomething(){
6
        return myService.getHello();
7
    }
8
}



While better than just using a private field, testing becomes a headache. You either need to bring up the Spring Context or use some Spring utilities to perform dependency injection for testing. Not the end of the world, but generally annoying.

We can improve upon this by providing a setter for the private property. Getters and setters are generally considered best practices in object-oriented programming. It's trivial to instruct Spring to use the setter for dependency injection by annotating the setter method.

Method Injection

Setter Controller

Java
 




xxxxxxxxxx
1
12


 
1
@Controller
2
public class SetterController {
3
    private MyService myService;
4
    @Autowired
5
    public void setMyService(MyService myService) {
6
        this.myService = myService;
7
    }
8
    public String saySomething(){
9
        return myService.getHello();
10
    }
11
}


This is a clear improvement upon using a private field. Some will complain this is too much code to write. But in reality, tasks like this have been automated in modern IDEs since season one of South Park.

Constructor Injection

The next option is to use a constructor. This is the best method we have looked at so far. When using a constructor to set injected properties, you do not have to provide the autowire annotation. This is a nice feature, which saves us a bit of typing. Annotation of constructors for dependency injection has been optional since Spring Framework version 4.2.

Constructor Controller

Java
 




xxxxxxxxxx
1
10


 
1
@Controller
2
public class ConstructorController {
3
    private MyService myService;
4
    public ConstructorController(MyService myService) {
5
        this.myService = myService;
6
    }
7
    public String saySomething(){
8
        return myService.getHello();
9
    }
10
}


Constructor-based dependency injection is certainly considered a best practice. There was a time I personally favored setter-based injection, but I have come around to constructor-based.

We can still improve our example. There are two main concerns right now. One, the type of our service is a concrete type. Dependency injection of a hard type is not considered a best practice.

The second problem is that the property we are injecting is not declared final. Thus, in theory, the class could modify the injected property after it was instantiated.

Dependency Injection Best Practices

Best practices for dependency injection is to utilize interfaces, constructors, and final properties.

I’ve set up a ‘best practice’ service interface and provided a service implementation – which is annotated with the Spring Service annotation.

Best Practice Service Interface

Java
 




xxxxxxxxxx
1


 
1
public interface BpService {
2
    String getHello();
3
}


Best Practice Service Implementation

Java
 




xxxxxxxxxx
1


 
1
@Service
2
public class BpServiceImpl implements BpService {
3
    @Override
4
    public String getHello() {
5
        return "The Best Hello!";
6
    }
7
}



Using Project Lombok

Now, the secret sauce using Project Lombok for best practices in dependency injection is to:

  • Declare a final property of the interface type
  • Annotate the class using Project Lombok’s required args constructor

Now, Project Lombok will generate a constructor for all properties declared final. And Spring will automatically use the Lombok provided constructor to autowire the class.

Lombok Controller

Java
 




x


 
1
@RequiredArgsConstructor
2
@Controller
3
public class BpFinalConstructorController {
4
    private final BpService bpService;
5
    public String saySomething(){
6
        return bpService.getHello();
7
    }
8
}



This is a real nice way of doing this. Your code stays very clean. When working with Spring, it’s not uncommon to need several autowired properties.

When you need to add another bean, simply declare a final property.

If you refactor, and no longer need a Spring managed dependency, just delete the final property.

You’re no longer maintaining setters or constructor code. Project Lombok alleviates this mundane task from you.

I’ve been using this technique for sometime now in my day-to-day coding. It’s definitely a timesaver. And leads to cleaner code. Gone are unused properties and unused constructor parameters. Refactoring is just a little less painful now!

Source code for this post is available here on GitHub.

Further Reading

How Dependency Injection (DI) Works in Spring Java Application Development

Optional Dependency Injection in Spring

Spring Framework Dependency injection

Published at DZone with permission of John Thompson, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Smart Dependency Injection With Spring: Assignability (Part 2 of 3)
  • Smart Dependency Injection With Spring: Overview (Part 1 of 3)
  • Smart Dependency Injection With Spring - Generics (Part 3/3)
  • Introduction to Apache Kafka With Spring

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!