Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Spring context initialization order

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.

like image 946
Jan Avatar asked Apr 12 '11 08:04

Jan


People also ask

What is the order of bean creation in Spring?

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.

How does Spring context work?

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.

Which are the correct implementation classes of ApplicationContext?

FileSystemXmlApplicationContext is the implementation class of ApplicationContext.

What is Spring order?

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.


1 Answers

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).

like image 79
Stijn Geukens Avatar answered Oct 02 '22 12:10

Stijn Geukens