Online problem: FeignClient circular dependency and source code analysis

1 scene reproduction

Dependency relationship: the left side of the dotted line is the implemented class, and the right side of the dotted line is Spring's native interface class or annotation.
Normally, there is no circular dependency, but in actual operation, the exception message: Is there an unresolvable circular reference?
clearly informs that there may be a circular dependency, and further investigation is required from the exception log.
insert image description here

1.1 FeignClient

Call the service through Feign.
insert image description here

1.2 HandlerInterceptor

Create a new Token interceptor.
insert image description here

1.3 WebMvcConfigurer

Add Token interceptor.
insert image description here

1.4 Controller

The interface depends on FeignClient.
insert image description here

2 options

Add @Lazy to FeignClient of TokenInterceptor, and do not load FeignClient of TokenInterceptor when starting SpringBoot. After the service is started, it will be loaded again when necessary, so that there is no need to repeatedly verify the singleton FeignClient when starting to ensure that the service starts normally.
insert image description here

3 analysis

When SpringBoot starts, the stack information is as follows: an exception is thrown from the inside out, and
there are many exception information, which can be seen in sections.

  • first paragraph
    org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘rpcApi’: Unsatisfied dependency expressed through field ‘feignTemplateService’; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration’: Unsatisfied dependency expressed through method ‘setConfigurers’ parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘webMvcHandler’: Unsatisfied dependency expressed through field ‘tokenInterceptor’; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘tokenInterceptor’: Unsatisfied dependency expressed through field ‘templateService’; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ‘com.monkey.tutorial.common.rpc.IFeignTemplateService’: Requested bean is currently in creation: Is there an unresolvable circular reference?

  • second paragraph
    Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration’: Unsatisfied dependency expressed through method ‘setConfigurers’ parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘webMvcHandler’: Unsatisfied dependency expressed through field ‘tokenInterceptor’; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘tokenInterceptor’: Unsatisfied dependency expressed through field ‘templateService’; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ‘com.monkey.tutorial.common.rpc.IFeignTemplateService’: Requested bean is currently in creation: Is there an unresolvable circular reference?

  • 第三段
    Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘webMvcHandler’: Unsatisfied dependency expressed through field ‘tokenInterceptor’; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘tokenInterceptor’: Unsatisfied dependency expressed through field ‘templateService’; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ‘com.monkey.tutorial.common.rpc.IFeignTemplateService’: Requested bean is currently in creation: Is there an unresolvable circular reference?

  • 第四段
    Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘tokenInterceptor’: Unsatisfied dependency expressed through field ‘templateService’; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ‘com.monkey.tutorial.common.rpc.IFeignTemplateService’: Requested bean is currently in creation: Is there an unresolvable circular reference?

  • 第五段
    Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ‘com.monkey.tutorial.common.rpc.IFeignTemplateService’: Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:355) ~[spring-beans-5.3.6.jar:5.3.6]

3.1 Abnormal positioning

From the fifth paragraph of exception information, you can locate the location where the exception is thrown:
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation,
this method is the verification before creating a singleton object, the source code is shown in the figure below:
insert image description here
from the source code , Before creating a singleton object, it will check whether the singleton object to be created is in the current collection through beforeSingletonCreation. According to the judgment logic of the source code, if the singleton object name (beanName) to be created is in singletonsCurrentlyInCreation, an exception will be thrown.

3.2 Debugging scheme

Through exception location and logical analysis of thrown exceptions,
breakpoint debugging can be interrupted at beforeSingletonCreation. The following is the debugging information of several core locations: rpcApi, WebMvcHandler, TokenInterceptor and IFeignTemplateService.

3.2.1 rpcApi

The rpcApi verification creation singleton object debugging information is shown in the following figure. On
the right side of the figure, the this.singletonsCurrentlyInCreation collection is empty, so the verification can be passed.
insert image description here

3.2.2 IFeignTemplateService

Enter IFeignTemplateService verification, because rpcApi depends on IFeignTemplateService,
therefore, after rpcApi verification is completed, it will enter IFeignTemplateService verification, the
debugging result is shown in the figure below, as can be seen from the figure, this.singletonsCurrentlyInCreation of IFeignTemplateService already has an element rpcApi,
that is, rpcApi depends on IFeignTemplateService , and IFeignTemplateService is not in the collection singletonsCurrentlyInCreation, so the verification is passed.

insert image description here

3.2.3 mvcResourceProvider

Next, the step of verification will be intercepted by mvcResourceUrlProvider, and
the mvcResourceUrlProvider verification will be performed first.
The debugging result is shown in the figure below. It can be seen from the figure that rpcApi and IFeignTemplateService already exist in this.singletonsCurrentlyInCreation,
indicating that rpcApi and IFeignTemplateService depend on mvcResourceUrlProvder . At this time , the verification is passed,
the core here is: IFeignTemplateService has been added to this.singletonsCurrentlyInCreation, which is the introduction of subsequent exception throwing .
insert image description here

3.2.4 webMvcHandler

mvcResourceUrlProvider depends on webMvcHandler.
After mvcResourceUrlProvider passes the verification, it will enter the webMvcHandler verification.
The debugging result is shown in the figure below. As can be seen from the figure, webMvcHandler passed the verification without exception.
insert image description here

3.2.5 tokenInterceptor

webMvcHandler relies on tokenInterceptor. After verifying webMvcHandler, it will enter tokenInterceptori verification.
The tokenInterceptor verification process is shown in the figure below, and the verification is passed.
insert image description here

3.2.6 IFeignTemplateService

Since tokenInterceptor also depends on IFeignTemplateService,
after the tokenInterceptor is verified, it will continue to verify IFeignTemplateService. The
debugging process is shown in the figure below. Based on the above analysis, IFeignTemplateService already exists in this.singletonsCurrentlyInCreation (
because IFeignTemplateService depends on mvcResourceUrlProvider; mvcResourceUrlProvider depends on webMvcHandler)
Validation fails and an exception is thrown.
insert image description here
Throw an exception
insert image description here

3.3 Cyclic dependencies

After analysis, the formed circular dependency is shown in the figure below.

insert image description here

3.4 Solve

In order to ensure the SpringBoot service, it is necessary to break the circular dependency.
Therefore, in the TokenInterceptor, FeignClieit is not loaded when the service is started, and the
@Lazy annotation is added to FeignClient to delay loading. After the service is started, it is loaded when there is a call.
insert image description here

4 Summary

(1) Cyclic dependencies have explicit dependencies: such as A->B->C->A, and implicit dependencies, which need to be debugged step by step; (2)
Solutions for circular dependencies: break the loop, adjust code design, delay loading etc.

Guess you like

Origin blog.csdn.net/Xin_101/article/details/130034641