This article has participated in the “Digitalstar Project” and won a creative gift package to challenge the creative incentive money.


A romantic getaway on sunset Boulevard that no one knows but the wind

preface

Hello everyone, I am one

Recently I was very upset by the interview, especially when I saw some interviewers coming up with a black face. I really wanted to finish the interview quickly.

But in order to live, or have to endure, in the final analysis is too dish!

Recently, some fans asked about circular dependency. If someone asks you again in the future, use this article to “beat” him.

concept

What are circular dependencies?

Multiple beans depend on each other to form a closed loop. For example, A depends on B, B depends on C, and C depends on A.

In general, if you ask the Spring container how loop dependencies are handled internally, you are referring to the default singleton Bean in which the injected properties are constructed to reference each other based on the set method.

The types of cyclic dependencies and whether they can be resolved are as follows:

The name of the Whether circular dependencies can be resolved
Constructor loop dependencies no
Setter loop dependency is
Prototype scope loop dependencies no

Error message

Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'myDao' : Requested bean is currently in creation: Is there an unresolvable circular reference?Copy the code

translation

The dependency represented by the constructor parameter 0 is not satisfied; The nested exception is an error creating a bean named 'myDao'. The requested Bean is currently being created. Is there a circular reference that cannot be resolved?Copy the code

Exception information: bean current abnormal create org. Springframework. Beans. Factory. BeanCurrentlyInCreationException.

Popular understanding

The two men confronted each other with guns

Now a b two people, take a gun to confront each other, a say b put first, b say a put first. Just don’t shoot.

Ah, play!

I believe we have seen this scene in the TV series, the final is usually “the villain died of talking too much”.

But back in Spring, we don’t want anyone to die, so both beans have to be created. What do we do?

One of us has to compromise

The solution: one of us has to compromise first.

A say: I step back, I unload the clip first, you put the gun down.

B a listen to touched, full of tears with a gun down.

A see b did not hit himself, also tears, two people tightly embrace.

And lived happily ever after…

The Spring edition of understanding

Back in Spring, let’s review the bean lifecycle:

  • instantiation
  • Attribute assignment
  • Initialize the
  • The destruction

Just to understand the above process

instantiationandInitialize theWhat’s the difference?

Is only the intermediate assignment missing, and is the instantiated bean usable?

Of course not!

That is to say, only the instantiated bean is a semi-finished product and can be used only after initialization.

Now A depends on B, and B depends on A.

A to B: I want the whole of you

A: I want the whole of you

Okay, there’s a fight going on. Gun to gun. How to solve it? I don’t know if I have to compromise alone.

A said: forget it, you give me your semi-finished product, I will settle.

B thought to himself, he can use my semi-finished product to create a complete, then I can create.

Think so, the mouth readily said: ok, no problem.

In this way, A creates a complete version of herself, and B takes a and completes the creation.

Problem solved.

Did it really work out? Where are finished and semi-finished products?

This brings us to the famous level 3 cache.

Three levels of cache

Spring provides a three-level cache to store finished and semi-finished products and factories. Located in DefaultSingletonBeanRegistry class.

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {   
	/** * Level 1 cache: singleton pool * holds initialized beans -- finished product */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
    /** * Level 3 cache: the cache of the singleton factory * the factory where the generated beans are stored */
    private finalMap<String, ObjectFactory<? >> singletonFactories =new HashMap(16);
    /** * Level 2 cache: a cache of early singleton objects * holds beans that have been instantiated but not initialized (not populated with attributes) -- a semi-finished product */
    private final Map<String, Object> earlySingletonObjects = new HashMap(16);
}
Copy the code

Creation Process (Easy version)

If you are a surprise interview, it is recommended to put the easy version down to meet the interview

Wait for time to look at the source version

If A depends on B, and B depends on A, there is A circular dependency between the two classes

  • A starts by creating an instance of the bean through its no-argument constructor, and exposes the instance in advance by putting it into A “level 2 cache”. A stop.
  • B starts to create, first go to the “level 1 cache” to find the finished product of A, can not find it, and then go to the “level 2 cache”, still can not find it, and then go to the “level 3 cache” to find the creation factory of A, through the factory, get the semi-finished product of A, and put A into the “level 2 cache”.
  • After getting A, B completes the creation and puts itself in “level 1 cache”.
  • At this point, A continues to create, also from the “level 1 cache” to find, after B to complete the creation, put itself into the “level 1 cache”.

Creation process (source version)

Source version recommended with Spring source code side debug side to eat.

1. When we call getBean() to get the bean, we are actually calling the doGetBean() method. DoGetBean () wants to get beanA, so it calls the getSingleton() method to look up the beanA from the cache

GetSingleton () returns null from level 1 cache

GetSingleton () = ObjectFactory (); getSingleton() = ObjectFactory ();

4. In the getSingleton() method, beanA_name is added to a collection to indicate that the bean is being created, and then the createBean method of the anonymous inner class is called back

5, enter AbstractAutowireCapableBeanFactory# doCreateBean, first reflection calls the constructor to create beanA instance, and then judge, whether as a singleton, BeanA is added to the “level 3 cache” if it is true whether the reference is allowed to be exposed ahead of time (typically true for singleton cases), whether it is being created (that is, whether it is in the collection of step 4)

6. Fill the attributes of beanA. At this time, it is detected that beanA depends on beanB, so beanB is searched

Call the doGetBean() method as beanA did above, query the beanB in the cache, create the beanB, and fill the beanB with attributes

GetSingleton () is called to obtain beanA from level 1, Level 2 and level 3 caches successively. At this time, beanB obtains beanA’s creation factory from “Level 3 Caches”, and obtains singletonObject by creating the factory. This singletonObject points to the beanA instantiated above in the doCreateBean() method

9. BeanB gets beanA’s dependencies, and beanB successfully completes initialization and moves beanA from “level 3 cache” to “Level 2 cache”

10. BeanA then proceeds with the property population, gets the beanB, completes the creation, and returns to getSingleton() to move beanA from “level 2 cache” to “level 1 cache.

The last

My friend designed a new logo for me, which one do you think is better?

Comments can be entered into a raffle, nuggets officials will be at the end of the Diggnation project in the comments section of 100 nuggets.

In order to give back to your fans, we prepared a high-quality resources accumulated for many years, including learning videos, interview materials, treasured e-books, etc. To receive