问题:项目启动时报出错误信息,
The dependencies of some of the beans in the application context form a cycle:
┌─────┐ ````| intermediateService defined in file [E:\projects\business-server\target\classes\com\hyit\business\server\Intermediate\IntermediateService.class] ````↑ ↓ ````| accountTreeServiceImpl defined in file [E:\projects\business-server\target\classes\com\hyit\business\server\service\impl\AccountTreeServiceImpl.class]
以上信息是由于,服务之间出现相互注入,之后产生循环依赖,我开始使用中间服务,进行解决,但是仍然报出错误。
猜想:
由于此项目性能过差,不能在使用懒加载和构造注入来解决问题。
解决方案:
放弃使用自动注入的方式,使用手动依赖查找来满足需求,依赖查找的方式是指,在需要依赖的时候从容器中获取对应的 Bean 对象,而不是在构造函数或setter方法中注入。具体方法是创建一个对象工厂,然后从 BeanFactory 中获取需要的依赖。这种方式可以避免循环依赖。
实现如下:
@Service public class IntermediateService { private final AccountTreeService accountTreeService; private final BaseOrgDataAuthService baseOrgDataAuthService; public IntermediateService(AccountTreeService accountTreeService, BaseOrgDataAuthService baseOrgDataAuthService) { this.accountTreeService = accountTreeService; this.baseOrgDataAuthService = baseOrgDataAuthService; } public AccountTreeService getAccountTreeService() { return accountTreeService; } public BaseOrgDataAuthService getBaseOrgDataAuthService() { return baseOrgDataAuthService; } }
@Component public class IntermediateServiceFactory implements BeanFactoryAware { private BeanFactory beanFactory; private volatile IntermediateService intermediateService; @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } /** * * 暂定使用volatile保证并发和性能问题 */ public IntermediateService getIntermediateService() { if (intermediateService == null) { synchronized (this) { // 加锁 if (intermediateService == null) { intermediateService = beanFactory.getBean(IntermediateService.class); } } } return intermediateService; } }
关于为什么手动查找依赖对象可以避免并解决相互依赖的问题
在 Spring 容器中,当两个 Bean 互相依赖时,容器必须确定将哪个 Bean 注入给先创建的 Bean。如果采用自动注入或setter方法注入依赖对象,Spring 容器会根据配置的注入顺序和 Bean 定义信息自动完成依赖注入,而这种自动注入或setter方法注入的方式存在循环依赖问题。
当 A 和 B 两个 Bean 互相依赖时,如果采用自动注入或setter方法注入依赖对象,Spring 容器会先创建 A 实例,然后发现 A 需要依赖 B,于是容器又会创建 B 实例。但是创建 B 实例的过程中,发现 B 又需要依赖 A,于是容器又会返回已经创建过的 A 实例,但是此时 A 的依赖 B 尚未被注入完成,导致出现循环依赖的问题。
而采用依赖查找的方式获取依赖对象,则不会出现循环依赖问题。因为依赖查找是由代码手动触发的,可以控制依赖对象的获取顺序和时机。因此,即使存在循环依赖,也可以通过工厂类等手动进行延迟注入,从而避免了循环依赖问题。
总之,手动查找依赖对象可以对依赖关系进行更细粒度的控制,避免了自动注入或setter方法注入方式可能产生的循环依赖问题。但是,手动查找的方式同时也增加了代码的复杂度,需要更多的代码和维护工作,因此需要根据具体情况进行选择。
标签:依赖,IntermediateService,intermediateService,Bean,循环,解决,public,注入 From: https://www.cnblogs.com/stephenllf/p/17843835.html