本文记录处理一个SpringBoot拦截器注入Feign接口导致的循环依赖的问题。

问题描述

SpringBoot项目代码中,存在一个AuthInterceptor implements HandlerInterceptor以完成接口的授权验证。当程序启动时,发生如下错误:

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: 
	Error creating bean with name 'mvcResourceUrlProvider': Requested bean is currently in creation: Is there an unresolvable circular reference?

7|api  | 2020-12-29 17:35:58 +08:00: APPLICATION FAILED TO START
7|api  | 2020-12-29 17:35:58 +08:00: ***************************
7|api  | 2020-12-29 17:35:58 +08:00:
7|api  | 2020-12-29 17:35:58 +08:00: Description:
7|api  | 2020-12-29 17:35:58 +08:00:
7|api  | 2020-12-29 17:35:58 +08:00: The dependencies of some of the beans in the application context form a cycle:
7|api  | 2020-12-29 17:35:58 +08:00:
7|api  | 2020-12-29 17:35:58 +08:00:    forumController (field private com.demo.openapi.OpenApiClient com.demo.controller.ForumController.openApiClient)
7|api  | 2020-12-29 17:35:58 +08:00: ┌─────┐
7|api  | 2020-12-29 17:35:58 +08:00: |  com.demo.openapi.OpenApiClient
7|api  | 2020-12-29 17:35:58 +08:00: ↑     ↓
7|api  | 2020-12-29 17:35:58 +08:00: |  org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration
7|api  | 2020-12-29 17:35:58 +08:00: ↑     ↓
7|api  | 2020-12-29 17:35:58 +08:00: |  webMvcConfig (field com.demo.interceptor.AuthInterceptor com.demo.config.WebMvcConfig.authInterceptor)
7|api  | 2020-12-29 17:35:58 +08:00: ↑     ↓
7|api  | 2020-12-29 17:35:58 +08:00: |  authInterceptor (field private com.demo.openapi.OpenApiClient com.demo.interceptor.AuthInterceptor.openApiClient)
7|api  | 2020-12-29 17:35:58 +08:00: ↑     ↓
7|api  | 2020-12-29 17:35:58 +08:00: |  mvcResourceUrlProvider
7|api  | 2020-12-29 17:35:58 +08:00: └─────┘
7|api  | 2020-12-29 17:35:58 +08:00:
7|api  | 2020-12-29 17:35:58 +08:00:

回顾这个问题出现的原因,是由于为了统一添加授权检查,我在interceptor中添加了一个feignClient。而之前在controller中注入feignClient是没有问题的。分析到这里,说明在interceptor中注入openApiClient时,SpringBoot框架对Bean的处理出了问题。为了解决这个问题,我们可以采用延迟加载的方式。这里用到注释@Lazy

SpringBoot@Lazy的说明

在拦截器注入FeignClient时,不需要spring的自动注入, 而是手动从Spring上下文中获取bean 既然拦截器中注入的OpenApiClient,那么我们将它延时注入,启动时不将feignClient注入,而是在拦截器被配置初始化时进行注入,这不正是@Lazy注解的功能嘛。 @Lazy:延时加载。仅对单例Bean生效。而单例Bean是在Spring容器启动的时候加载的,添加@Lazy注解后就会延迟加载,在Spring容器启动的时候并不会加载,而是在当你第一次使用此bean的时候才会加载,但当你多次获取bean的时候不会重复加载。 按照上述思路,修改代码