GCP环境遇org.springframework.beans.factory.UnsatisfiedDependencyException异常
问题背景
本地服务运行正常,但GCP环境出现以下异常:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'portfolioCommonServiceImpl': Unsatisfied dependency expressed through field 'portfolioFolderDao'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'portfolioFolderDaoImpl': Bean with name 'portfolioFolderDaoImpl' has been injected into other beans [portfolioServiceImpl] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.
已尝试在portfolioFolderDao上添加@Lazy注解,但问题未解决。
可行解决方案
1. 排查本地与GCP的配置差异
GCP环境可能开启了本地未启用的代理或切面(如事务代理、AOP),导致Bean被动态包装,触发循环依赖问题:
- 检查GCP专属配置文件(如
application-gcp.properties),确认是否有spring.aop.proxy-target-class=true、额外的切面配置或事务属性设置。 - 对比本地配置,关闭GCP环境中不必要的代理或切面,或调整其触发时机。
2. 调整@Lazy的注入位置
单独在portfolioFolderDao上加@Lazy可能无效,尝试将注解移到依赖它的Bean的注入点:
- 字段注入方式:
@Service public class PortfolioServiceImpl { @Autowired @Lazy private PortfolioFolderDao portfolioFolderDao; // 业务逻辑 } - 构造函数注入方式(更推荐,Spring对构造函数注入的循环依赖处理更稳定):
@Service public class PortfolioServiceImpl { private final PortfolioFolderDao portfolioFolderDao; public PortfolioServiceImpl(@Lazy PortfolioFolderDao portfolioFolderDao) { this.portfolioFolderDao = portfolioFolderDao; } // 业务逻辑 }
3. 彻底拆解循环依赖(最优方案)
通过提取公共逻辑打破PortfolioServiceImpl与PortfolioFolderDaoImpl之间的循环:
- 创建新的辅助类,将两个Bean互相调用的逻辑迁移到该类中:
@Service public class PortfolioBizHelper { // 原PortfolioServiceImpl与PortfolioFolderDaoImpl交叉调用的逻辑 public void handleCommonPortfolioLogic() { // 具体实现 } } - 修改两个Bean,注入辅助类而非互相注入:
@Service public class PortfolioServiceImpl { private final PortfolioBizHelper bizHelper; public PortfolioServiceImpl(PortfolioBizHelper bizHelper) { this.bizHelper = bizHelper; } // 业务逻辑调用bizHelper } @Service public class PortfolioFolderDaoImpl implements PortfolioFolderDao { private final PortfolioBizHelper bizHelper; public PortfolioFolderDaoImpl(PortfolioBizHelper bizHelper) { this.bizHelper = bizHelper; } // DAO逻辑调用bizHelper }
4. 调整Spring的Bean初始化策略
按照异常提示,关闭过早的类型匹配,或强制生成代理对象:
- 全局关闭 eager 类加载:
@Configuration public class AppConfig { @Bean public static BeanFactoryPostProcessor beanFactoryPostProcessor() { return beanFactory -> beanFactory.setAllowEagerClassLoading(false); } } - 为循环依赖Bean设置代理模式:
在PortfolioFolderDaoImpl或PortfolioServiceImpl上添加注解,确保注入的是代理对象而非原始Bean:@Service @Scope(proxyMode = ScopedProxyMode.TARGET_CLASS) public class PortfolioFolderDaoImpl implements PortfolioFolderDao { // 实现代码 }
内容的提问来源于stack exchange,提问作者Anukul

