๐ด The Error You're Seeing
Confirm this matches your console output. If it does, you're in the right place.
2023-10-25 10:15:30.812 ERROR 12345 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'userService': Bean with name 'userService' has been injected into other beans [userProfileService] in its raw object as part of a circular reference, but was eventually wrapped. This means that said other beans do not use the final version of the bean.โก Quick Fix Works 80% of the time
Add @Lazy to one of the injections to break the creation cycle.
@Service
public class UserService {
public UserService(@Lazy UserProfileService profileService) { ... }
}๐ ๏ธ Solutions (3 Ways to Fix)
Use @Lazy annotation
๐ Use this for a quick fix when you can't refactor the architecture immediately.
Tells Spring to inject a proxy instead of the real bean. The real bean is only created when actually used, breaking the creation cycle.
@Service
public class UserService {
private final UserProfileService userProfileService;
public UserService(@Lazy UserProfileService userProfileService) {
this.userProfileService = userProfileService;
}
}Refactor to a Third Bean
๐ Use this when you have time to write clean code.
Extract the shared logic that both A and B need into a new Bean C. Now A -> C, and B -> C. No circle.
// Create a new shared service
@Service
public class SharedLogicService { ... }
// Inject it into A and B
@Service
public class UserService {
@Autowired SharedLogicService shared;
}Use Setter Injection instead of Constructor
๐ Use this in legacy codebases where you can't use @Lazy.
Constructor injection requires beans to be fully formed before injection. Setter injection allows Spring to inject an unfinished bean, resolving the cycle.
@Service
public class UserService {
@Autowired
public void setUserProfileService(UserProfileService service) {
this.userProfileService = service;
}
}๐ Version Notes
Circular references were allowed by default.
Circular references are disabled by default. Crashes unless spring.main.allow-circular-references=true is set.
๐ง Why this Happens
Tap to expand the deep technical explanation
A circular dependency occurs when Bean A depends on Bean B, and Bean B depends on Bean A (A -> B -> A). Spring tries to create A, sees it needs B, tries to create B, sees it needs A, and realizes A isn't finished creating yet. Spring Boot 3.2+ disables circular references by default, causing a crash.
The HITEC City Parking Spot Analogy:
It's like two people trying to paint a portrait of each other. Person A can't finish painting B until B sits still, but B can't sit still because they are trying to paint A.
๐ก๏ธ How to Prevent This Next Time
Keep your service layer flat. If two services need the same logic, extract it into a third shared service.