本文记录处理一个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的时候不会重复加载。
按照上述思路,修改代码