Best Practices for Dependency Injection in Spring

preview_player
Показать описание
The Spring Framework has robust dependency injection capabilities.

Using Spring you can perform dependency injection using public properties, private properties, via setter methods, and via constructors.

But which dependency injection method is the best to use? And how can Project Lombok help you?

Check out this video to learn the do's and don't of dependency injection with Spring!

Post -
In this video, I'm going to show you how to use Project Lombok for best practices in autowiring 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.

I've setup 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. 

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

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. 

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. Its trivial to instruct Spring to use the setter for dependency injection by annotating the setter method.

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

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.12.

Constructor based dependency injection is certainly considered a best practice. There was a time I personally favored setter based injection, but 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, the property we are injecting is not declared final. Thus, in theory, the class could modify the injected property after it was instantiated. 

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

I've setup a 'best practice' service interface, and provided a service implementation - which is annotated with the Spring Service annotation. 

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 clase 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 clase. 

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!
Рекомендации по теме
Комментарии
Автор

Hi John,
thanks for the video!

I understood the statements, but I did not understand the why.
1) Can you please elaborate more on why not using the final keyword (3:20) is a bad practice? What issues do I get by not using the final and what pros do I get when using the final?
2) Can you also elaborate why is it a headache to unit test (1:32)? Do you have time to record a second part of the video showing the differences in unit testing the controllers and the examples of headaches?
3) Why is the private field injection based approach not the recommend way? I have to confess that I am using it.

I have one general feedback regarding your videos. I like how you compare things and show differences. What I personally miss is that you rarely show the differences at the same time, rather you are jumping from one place to another and then talking about differences. So what I do is that I take a screenshot when you are in one class and a screenshot when you are in an another class and then highlight the differences for myself. For example: taking a screenshot of the FieldController class and then later a screenshot of PrivateFieldController class and mark the difference which you mention. Those visualisations help me learn faster. I dunno if other people feel the same. My idea would be to show both classes at the same time (Split Vertically) and then while talking about differences also highlighting them.

Keep up the great work and thank you for sharing your knowledge!

pefi
Автор

Awesome! Thank you. The annotation @RequiredArgsConstructor is great!

_jormanespinoza
Автор

Apart from making the testing easy, can you elaborate why constructor based injection is the Best way.

MohammedNizamuddin
Автор

Thanks, good tutorial. For me the font size is good on smartphone. Just increase the video quality when watching to see the text properly

Fred_Klingon
Автор

Implementing beans through interfaces is really the way to go. Just to highlight it more. It will allow you to have multiple bean implementations and you don't need to modify existing code everywhere, you just mark one implementation as @Primary and use another with @Qualifier

kyryloshpak
Автор

How we will use this in case of cyclic dependency??

jahid
Автор

What happen if I have multiple constructors in my class and final variables? This constructor is not gonna work

abajoaladerecha
Автор

Please consider increasing the font size in the coming videos since A) there are a lot of people who watch the videos on the smartphone or on the tablet and B) that helps the lerners to fosus on what you are typing.
If you like you could see for example the way how the tutorials from *Mosh Hamedani* are recorded

Nevertheless, the content in your videos and your knowledge are perfect, thanks a lot for sharing👍👍

tomaspyth
Автор

Thanks for the video but I believe using lombok is not the best practice. Using the auto-wired by constructor is the best and defining the Named bean in service can make it better

manizaeim