𝗦𝘁𝗼𝗽 𝘂𝘀𝗶𝗻𝗴 @𝗔𝘂𝘁𝗼𝘄𝗶𝗿𝗲𝗱 𝗼𝗻 𝘆𝗼𝘂𝗿 𝗳𝗶𝗲𝗹𝗱𝘀. Today I want to talk about a topic that I learned on LinkedIn some time ago. When working with Spring Boot, most introductory courses teach dependency handling by the use of 𝗙𝗶𝗲𝗹𝗱 𝗜𝗻𝗷𝗲𝗰𝘁𝗶𝗼𝗻. Even though it works for its purpose, you end up with a tight coupling between your class and the Spring Container. A much better option is to use 𝗖𝗼𝗻𝘀𝘁𝗿𝘂𝗰𝘁𝗼𝗿 𝗜𝗻𝗷𝗲𝗰𝘁𝗶𝗼𝗻. By injecting your dependencies directly into your constructor, you get several improvements: - 𝗜𝗺𝗺𝘂𝘁𝗮𝗯𝗶𝗹𝗶𝘁𝘆: Dependencies are declared as 𝘧𝘪𝘯𝘢𝘭, which prevents runtime mutation and eliminates an entire class of potential bugs. - 𝗡𝘂𝗹𝗹 𝗦𝗮𝗳𝗲𝘁𝘆: Your class is only instantiated when all dependencies are provided. This avoids Field Injection’s 𝘕𝘶𝘭𝘭𝘗𝘰𝘪𝘯𝘵𝘦𝘳𝘌𝘹𝘤𝘦𝘱𝘵𝘪𝘰𝘯, which can only be identified at runtime. - 𝗕𝗲𝘁𝘁𝗲𝗿 𝘁𝗲𝘀𝘁𝘀: When working with Field Injection, you end up having to add a @𝘚𝘱𝘳𝘪𝘯𝘨𝘉𝘰𝘰𝘵𝘛𝘦𝘴𝘵 and use complex tools like Reflection. While for 𝗖𝗼𝗻𝘀𝘁𝗿𝘂𝗰𝘁𝗼𝗿 𝗜𝗻𝗷𝗲𝗰𝘁𝗶𝗼𝗻, the creation of unit tests gets easier. You instantiate a service as a simple Java object declaration. This improves build and execution times significantly. Another great example on why Constructor Injection is a better option is how it handles 𝗖𝗶𝗿𝗰𝘂𝗹𝗮𝗿 𝗗𝗲𝗽𝗲𝗻𝗱𝗲𝗻𝗰𝗶𝗲𝘀. If 𝘚𝘦𝘳𝘷𝘪𝘤𝘦𝘈 depends on 𝘚𝘦𝘳𝘷𝘪𝘤𝘦𝘉, and 𝘚𝘦𝘳𝘷𝘪𝘤𝘦𝘉 depends on 𝘚𝘦𝘳𝘷𝘪𝘤𝘦𝘈, Field Injection might allow the application build and start, but eventually you would get a 𝘚𝘵𝘢𝘤𝘬𝘖𝘷𝘦𝘳𝘧𝘭𝘰𝘸𝘌𝘳𝘳𝘰𝘳. With 𝗖𝗼𝗻𝘀𝘁𝗿𝘂𝗰𝘁𝗼𝗿 𝗜𝗻𝗷𝗲𝗰𝘁𝗶𝗼𝗻, you will get an error on startup, forcing you to fix the error and make sure you don’t release a hidden Exception to production. As an additional tip, you can use Lombok’s @𝘙𝘦𝘲𝘶𝘪𝘳𝘦𝘥𝘈𝘳𝘨𝘴𝘊𝘰𝘯𝘴𝘵𝘳𝘶𝘤𝘵𝘰𝘳 annotation, which creates the constructor for all your 𝘧𝘪𝘯𝘢𝘭 dependencies, which means a better and cleaner code. Are you still using Field Injection in your legacy projects, or have you updated them to Constructor Injection? #Java #SpringBoot #BackendDevelopment #SoftwareEngineering #SpringFramework
Constructor injection on any DI mechanism for any language/framework is always a better pattern. Some times, due to legacy or poorly architected software, circular dependencies are necessary, then using property injection makes sense and it is very clear why it was used. Default to constructor injection, use property injection as a scape hatch.
Nice post, thanks for sharing :)
Insightful, thanks for sharing
Great point! Constructor injection is one of those small habits that pays off everywhere: clearer dependencies, easier unit tests, and failures that show up early instead of at runtime. From a QA perspective, it also reduces “hidden wiring” bugs and makes services simpler to instantiate in isolated tests, which speeds up feedback in CI. In legacy code, I’ve had good results migrating incrementally, new code uses constructor injection, and the old parts get refactored when they’re touched.