๐ด The Error You're Seeing
Confirm this matches your console output. If it does, you're in the right place.
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
โโโโโโโ
| userService defined in file [/com/devinhyderabad/service/UserService.class]
โ โ
| userProfileService defined in file [/com/devinhyderabad/service/UserProfileService.class]
โโโโโโโ
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the cycle of dependencies between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.โก Quick Fix Works 80% of the time
Refactor the classes to extract shared logic into a 3rd bean, or use @Lazy.
@Service
public class UserService {
public UserService(@Lazy UserProfileService profileService) { ... }
}๐ง Why this Happens
Tap to expand the deep technical explanation
Bean A requires Bean B, and Bean B requires Bean A. Spring Boot 3 disabled circular references by default to promote clean architecture, causing the app to crash instead of resolving the loop.
The HITEC City Parking Spot Analogy:
Two people are trying to paint a portrait of each other. Person A won't sit still until Person B sits, and Person B won't sit until Person A sits. Nothing happens.
๐ How to Reproduce Confirm this is your error
Create `UserService` with `@Autowired UserProfileService`. Create `UserProfileService` with `@Autowired UserService`. Run the Spring Boot 3 app.
๐ ๏ธ Solutions (5 Ways to Fix)
Use @Lazy annotation
๐ Use this as a quick fix when you cannot 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.
@Service
public class SharedLogicService { ... }
@Service
public class UserService {
@Autowired SharedLogicService shared; // No cycle
}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;
}
}Re-enable circular references (Not Recommended)
๐ Use this ONLY as a last resort when migrating a massive legacy Spring Boot 2 app to Spring Boot 3.
Spring Boot 2 allowed this by default. You can turn the old behavior back on, but it's a band-aid.
# application.properties
spring.main.allow-circular-references=trueUse ApplicationContext to fetch bean at runtime
๐ Use this if the dependency is only needed for one specific method, not at startup.
Instead of autowiring, inject the ApplicationContext and get the bean when you need it.
@Service
public class UserService {
@Autowired
private ApplicationContext context;
public void doWork() {
UserProfileService service = context.getBean(UserProfileService.class);
service.doSomething();
}
}๐ Version Notes
Circular references were allowed by default.
Circular references are disabled by default. Crashes unless spring.main.allow-circular-references=true is set.
๐ก๏ธ 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.