I have a complex set of beans and dependencies between them. All beans are @Service
, @Repository
or @Controller
annotated and I use the @PostConstruct
annotation. There are some circular dependencies but still the system was correctly initialized by Spring.
Then I added a simple Controller with just a dependency to one of the Services. Theoretically, the system should be able to boot because theoretically it could first set up the system as before and then the new Controller. But Spring complains that it cannot set up the context:
Error creating bean with name 'userService': Requested bean is currently in creation: Is there an unresolvable circular reference?
Can I somehow assists Spring in how to order the context initialization? I think the main issue is the userService
which is used a lot through the system for authentication purposes.
The order in which Spring container loads beans cannot be predicted. There's no specific ordering logic specification given by Spring framework. But Spring guarantees if a bean A has dependency of B (e.g. bean A has an instance variable @Autowired B b; ) then B will be initialized first.
Spring contexts are also called Spring IoC containers, which are responsible for instantiating, configuring, and assembling beans by reading configuration metadata from XML, Java annotations, and/or Java code in the configuration files.
FileSystemXmlApplicationContext is the implementation class of ApplicationContext.
It means the highest order advice will run first. Since Spring 4.0, it supports the ordering of injected components to a collection. As a result, Spring will inject the auto-wired beans of the same type based on their order value. Let's explore it with a quick example.
Best solution would simply be to take out the circular dependency; I have not yet encountered a scenario where such a structure was warranted. But if you do want to stick with it then perhaps your above problem is due to the fact that you have constructor injection somewhere:
Circular dependencies If you are using predominantly constructor injection it is possible to write and configure your classes and beans such that an unresolvable circular dependency scenario is created. Consider the scenario where you have class A, which requires an instance of class B to be provided via constructor injection, and class B, which requires an instance of class A to be provided via constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container will detect this circular reference at runtime, and throw a BeanCurrentlyInCreationException.
One possible solution to this issue is to edit the source code of some of your classes to be configured via setters instead of via constructors. Another solution is not to use constructor injection and stick to setter injection only. In other words, while it should generally be avoided in all but the rarest of circumstances, it is possible to configure circular dependencies with setter injection. Unlike the typical case (with no circular dependencies), a circular dependency between bean A and bean B will force one of the beans to be injected into the other prior to being fully initialized itself (a classic chicken/egg scenario).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With