1 现象
主要改动点:
项目引入swagger文档
环境:
- 非生产环境:
- 打包:idea
- 应用启动:无异常(未能复现)
- 生产环境:
- 打包(docker容器内):maven:3.5.4-jdk-8
- 部署:docker
- 应用启动:报错
截取的报错日志信息(格式化后的):
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'webMvcObjectMapperConfigurer'
defined in class path resource [springfox/documentation/spring/web/SpringfoxWebMvcConfiguration.class]:
BeanPostProcessor before instantiation of bean failed;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'authorizationAttributeSourceAdvisor'
defined in class path resource [org/apache/shiro/spring/boot/autoconfigure/ShiroAnnotationProcessorAutoConfiguration.class]:
Unsatisfied dependency expressed through method 'authorizationAttributeSourceAdvisor' parameter 0;
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'org.apache.shiro.spring.config.web.autoconfigure.ShiroWebAutoConfiguration':
Unsatisfied dependency expressed through field 'rolePermissionResolver';
nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'shiroFilterFactoryBean'
defined in class path resource [website/ragnar/vks/configuration/ShiroConfiguration.class]:
Unsatisfied dependency expressed through method 'shiroFilterFactoryBean' parameter 0;
nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'securityManager':
Requested bean is currently in creation: Is there an unresolvable circular reference?
2 分析
从上面的报错信息,我们可以得到以下线索:
有三个异常类:
- BeanCreationException,即Bean创建异常;
- UnsatisfiedDependencyException,即不满足依赖异常;
- BeanCurrentlyInCreationException,即bean正在被创建异常。
猜测:
那就可能是shiroFilterFactoryBean
和securityManager
这两个bean可能存在循环依赖。
代码分析:
应用的配置类ShiroConfiguration
中定义了shiroFilterFactoryBean
:
@Configuration
@ConditionalOnProperty(name = "shiro.web.enabled", matchIfMissing = true)
public class ShiroConfiguration {
// ...
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager) {
// ...
}
// ...
}
而securityManager
即是用jar中org.apache.shiro.spring.config.web.autoconfigure.ShiroWebAutoConfiguration
定义的:
@Configuration
@AutoConfigureBefore(ShiroAutoConfiguration.class)
@ConditionalOnProperty(name = "shiro.web.enabled", matchIfMissing = true)
public class ShiroWebAutoConfiguration extends AbstractShiroWebConfiguration {
// ...
@Bean
@ConditionalOnMissingBean
@Override
protected SessionsSecurityManager securityManager(List<Realm> realms) {
return super.securityManager(realms);
}
// ...
}
由以上代码可以看出,shiroFilterFactoryBean
和securityManager
这两个bean没有直接的依赖关系。
间接依赖关系?
报错信息中有这样一个叫rolePermissionResolver
的bean,在ShiroWebAutoConfiguration
的父父类AbstractShiroConfiguration
中定义为成员变量,代码如下:
public class AbstractShiroConfiguration {
// ...
@Autowired(required = false)
protected RolePermissionResolver rolePermissionResolver;
// ...
}
这里并没有强制要求依赖注入,但为什么会抛出UnsatisfiedDependencyException
?
3 解决方案
根据上面分析,基本可以推断,shiroFilterFactoryBean
和securityManager
之间应该是存在间接性的循环依赖。
所以方案就是:采用懒加载方式。
在ShiroFilterFactoryBean
的@Bean上面加上@Lazy注解,be like:
@Lazy
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager) {
// ...
}
4 总结
- **编译打包环境要尽可能一致。**这环境上主要差别应该就在打包上了,因为下载来自生产环境的jar包能复现这个报错。
- **运行原理要尽可能了解和熟悉。**生产环境是基于gitlab做的自动化部署,当时是参考一些文档写的gitlab自动部署脚本,对其原理还不算了解。
注意:本文归作者所有,未经作者允许,不得转载