09 · Spring Framework and the IoC container / LESSON 39 OF 102
Constructor injection, optional dependencies, and cycles
Constructor injection makes required collaborators visible and lets objects start in a valid state.
Before this lesson: Component scanning and stereotype annotations
Understand the topic
A Spring bean with one constructor does not need @Autowired on that constructor. Store required dependencies in final fields. Field injection hides requirements and makes plain unit construction harder; setter injection is better reserved for genuinely optional or reconfigurable collaboration.
A constructor cycle means A needs B before A can exist while B needs A before B can exist. Resolve responsibility boundaries rather than hiding the cycle with lazy references. ObjectProvider is useful for deliberate deferred lookup, not as a substitute for design.
EXAMPLE · JAVA
TitleService.java
import org.springframework.stereotype.Service;
@Service
public class TitleService {
private final java.time.Clock clock;
public TitleService(java.time.Clock clock) { this.clock = clock; }
public java.time.Instant createdAt() { return clock.instant(); }
}What to expect
Register a Clock bean in configuration. Spring supplies it; a unit test can pass Clock.fixed directly.
YOUR TURN
Put it into practice
- 01Replace a field-injected dependency with a constructor.
- 02Write a plain Java test with a fixed Clock, then draw the dependency graph.
- 03Verify: No application service uses field injection or forms a constructor dependency cycle.
Pass a quiz or complete a lab to check today’s streak. Each lesson counts once per day, including when you review it later.
UNDER THE HOOD
Build the mental model
Constructor injection makes required collaborators visible and lets objects start in a valid state.
- 01A Spring bean with one constructor does not need @Autowired on that constructor. Store required dependencies in final fields. Field injection hides requirements and makes plain unit construction harder; setter injection is better reserved for genuinely optional or reconfigurable collaboration.
- 02A constructor cycle means A needs B before A can exist while B needs A before B can exist. Resolve responsibility boundaries rather than hiding the cycle with lazy references. ObjectProvider is useful for deliberate deferred lookup, not as a substitute for design.
- 03Trace the example: Register a Clock bean in configuration. Spring supplies it; a unit test can pass Clock.fixed directly.
A mistake worth avoiding
Startup reports a circular dependency between two services.
DEBUGGING ROOM
Something broke. Where do you look?
Startup reports a circular dependency between two services.
Before revealing the diagnosis, write down your first investigation step.
CHECK YOUR UNDERSTANDING
Does a single constructor normally need @Autowired?
BUILD IT YOURSELF
Replace a field-injected dependency with a constructor.
- 1.Replace a field-injected dependency with a constructor.
- 2.Write a plain Java test with a fixed Clock, then draw the dependency graph.
- 3.Reproduce this failure, then repair it: Startup reports a circular dependency between two services.
Acceptance checklist
Lab completion is your self-report. Knowledge checks do not certify project quality.
RETRIEVE IT FROM MEMORY
Does a single constructor normally need @Autowired?
Revisit this lesson in three days after a successful check or lab.
Ready for the next step?
No application service uses field injection or forms a constructor dependency cycle.
Reading is separate from passing a knowledge check or completing a lab.