I know you’ve been there, like me:
- I Have a circular dependency in Spring and my application fails to launch. How to solve this?
The typical exception thrown by Spring is the following:
‘org.springframework.security.authenticationManager’: Requested bean is currently in creation: Is there an unresolvable circular reference?
And, It does not give much details. So, let’s see how we can break the circular dependency cycle and save some sanity!
Understand the Issue
Let’s take a very simple example to illustrate the issue. Here is part of our code handling the application permissions.
SpringPermissionEvaluator then requires all the
PermissionByObject implementations to be injected via collection autowiring.
Suppose now that we have the following implementation named
We have a circular dependency here:
We’re going to explore the ways we can solve this issue.
The first and most obvious solution is to prevent the
WorkspaceByObject from requiring the
SystemPermissionEvaluator upon construction by using Field injection.
SystemPermissionEvaluator injected via Field Injection
Or Setter Injection:
SystemPermissionEvaluator injected via Setter Injection
Another solution would be to apply the same trick to the
SystemPermissionEvaluator. Why does it work? Because Spring can inject the dependencies after construction.
The @Lazy annotation allows Spring to inject a Java Proxy of your bean, instead of the bean itself. It can resolves the cycle by instantiating the beans when a method on it is called.
@Lazy proxyfies your bean, calls to your service are done through reflection, thus being 2x slower than direct calls. Therefore, I would recommend using
@Lazy only when nothing else is possible.
PostConstruct can be used to annotate a method which is then called once the bean has been properly autowired. It can be effectively used to fix a circular dependency, although you should be aware it’s pretty ugly to do so.
We can do so by altering the permission interface:
As you can see, this will pretty much affect every single
PermissionByObject implementation even if it’s not using the
Then, we’ll do this in the
Needless to say, this solution is exposing the internals of a specific permission to everyone. It’s also affecting permissions which don’t need the
SystemPermissionEvaluator being injected.
So, what can be do to solve this issue properly?
Another solution is to register the
PermissionByObject instances into the
SystemPermissionEvaluator using an external Spring Configuration within the same package. The key is to keep the registering logic invisible to external callers.
By doing this, the cycle is broken down. Both permission evaluator and permissions can be instantiated independently.
Changing the Code
A circular dependency issue should be an alarm screaming: Hey, there is something wrong with your code architecture! Of course, it’s not always possible to fix the issue by yourself. It may happen due to a badly designed library you are depending on.
After figuring it out, in fact the
WorkspaceByObject has been rewritten (as well as other parts of the permission system) to completely avoid injecting the
SystemPermissionEvaluator at all!
Always consider redesigning your code before deep diving into fancy solutions to fix spring circular dependencies issues. Use the methods described here as last resort when nothing else is possible.
Remember Spring isn’t difficult! There is a solution to every problem related to Spring, and chances are that you are not the single one experiencing those issues. Always look on Spring StackOverflow to see if someone else has had the same issue.