1. Bug site restoration

Circular dependencies

1.1, in the interceptor configuration class, rely on the interceptor by overriding addInterceptors to inject the interceptor into the interceptor chain.



The interceptor also relies on a thirdAuthClient by way of a constructor



1.3. ThirdAuthClient (a Feign client interface)



The project starts with an error, showing the three class cyclic dependencies

2. Bug analysis

2.1 hypothesis

ThirdAuthClient relies on ThirdInterceptorConfig. This is just an @feignClient. It should be loaded after Spring starts. The result can not be seen from the class diagram. It is suspected that it has something to do with the loading order of Spring beans. Although we see the cyclic dependency, it may actually be the wrong loading method.



2.2 comb

Let’s start by focusing on the injection method of the Spring MVC Interceptor



This is how interceptors are registered in the official documentation, straight out of new. The focus then becomes:

Why shouldn’t an Interceptor be injected via @autowired or a constructor?

I googled it and found this:

1. The default rule for SpringBoot project Bean assembly is to scan from top to bottom based on the package (com.boot.app) where the Application class resides

2. The interceptor executes before automatic bean initialization

Consistent with the hypothesis, consider whether the interceptor actually executes before automatic bean initialization

In my usage scenario, I think the correct order would be

  1. All of the interceptor’s dependencies, such as ThirdAuthClient, are initialized beans and injected into the Spring container

  2. Perform interceptor injection

  3. Initializes the interceptor bean object, requiring the existing bean object in 1 as a dependency for the interceptor

  4. Interceptor injection succeeded

If so, then statement 2 is not consistent with this idea, or the interceptor defined in the official documentation is a normal custom, no dependency, just new, whereas my custom interceptor explicitly declares dependencies through the constructor, and this difference may lead to circular dependencies.

I looked for other constructor injection methods, as follows



This can be done via @Bean injection, so the ThirdAuthClient that causes the interceptor loop dependency is injected via @AutoWired, and the other classes are injected via the constructor

This way, when I execute my idea of order 2, the beans needed for order 1 are ready.

3, the analysis

First, Spring loads and instantiates beans in the following order



The loop reference error should be detected by Spring during recursive parsing, and is related to the constructor I wrote to initialize the bean. The injection methods of interceptors seen on the Internet are basically manually created.

So the clear question here is:

1. Can interceptors be created manually (new out)? Can’t Spring manage objects and create them?

Analysis: This loading process involves the @ConfigurationProperties, @Component, @FeignClient, @Configuration, @Component annotations

The @ConfigurationProperties annotation belongs to the Spring configuration class annotation and is loaded first

@ FeignClient annotations by FeignClientsRegistrar class implements the ImportBeanDefinitionRegistrar, An interface to inject @FeignClient annotations into a container through the registerBeanDefinitions method

@Configuration and @Component are Configuration classes that Spring automatically loads

According to Spring’s logic for loading beans, these annotations are visible to Spring, and the dependencies of these instances can be analyzed recursively and instantiated when appropriate.

Such analysis, the problem is likely to be out in the constructor, the constructor of the display statement, replaced the Spring at the time of resolving these instances based on recursive, caused by these instances cannot be dependent on analytical solution, if you don’t use the constructor, so I think these annotations declared by the class is reliance can be placed in the Spring parsing.

4, implement

1. Manually create an interceptor instance implementation

The interceptor does not add any auto-configuration annotations, prevents Spring auto-assembly and initialization, and displays declaration dependencies through the constructor



The interceptor configuration class prepares the beans needed by the interceptor via the constructor and @AutoWired



In order 3, you manually create the interceptor instance via @bean, leaving the initialization of the interceptor to Spring.

This is done without changing the constructor mode, and it works.

2. Let the Spring container manage interceptor creation





This removes the constructor and uses annotations instead of creating interceptor instances manually, which is practical.

Five, the conclusion

Interceptor creation can be managed by Spring’s container management rather than by manual creation.

Reference documentation

www.cnblogs.com/shamo89/p/8…

Stackoverflow.com/questions/2…