循环依赖问题

什么是循环依赖?


循环依赖(Circular Dependency)指的是两个或多个模块之间相互依赖形成一个循环的情况。在软件开发中,循环依赖是一个不良的设计模式,可能导致一系列问题。

循环依赖可能出现在多个层面,例如:

模块之间的依赖循环:模块A依赖于模块B,同时模块B又依赖于模块A。
类之间的依赖循环:类A依赖于类B,同时类B又依赖于类A。
循环依赖会导致以下问题:

编译错误:在编译时,循环依赖可能导致无法解析的依赖关系,从而导致编译错误或无法生成可执行文件。
运行时错误:在运行时,循环依赖可能导致不可预测的行为、死锁或异常。 可维护性问题:循环依赖会增加代码的复杂性,使代码难以理解、测试和维护。 扩展困难:循环依赖会限制系统的扩展性,增加新功能或模块可能需要修改大量代码。

错误示范


fileServiceImpl内注入fileServiceImpl注入,加@Lazy注解延迟加载

代码:

@Autowired
    @Lazy
    private fileServiceImpl fileServiceImpl;

@Override @Transactional(rollbackFor = Exception.class) public UploadResultDto uploadFile(UserDto userDto, String fileId, MultipartFile file, String fileName, String filePid, String fileMd5, Integer chunkIndex, Integer chunks) { ...... // 事务提交后调用异步方法 TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { fileServiceImpl.transferFile(fileInfo.getFileId(), userDto); } }); ...... }

/** * 转码 * * @param fileId 文件标识 * @param userDto 用户dto */ @Async @Transactional(rollbackFor = Exception.class) public void transferFile(Long fileId, UserDto userDto) { ...... }

报错:


Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2023-05-31 22:16:57.999 ERROR 29452 --- [           main] o.s.boot.SpringApplication               : Application run failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fileController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'fileServiceImpl': Bean with name 'fileServiceImpl' has been injected into other beans [fileServiceImpl] 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. at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:332) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.1.jar:2.6.1] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730) [spring-boot-2.6.1.jar:2.6.1] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:412) [spring-boot-2.6.1.jar:2.6.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:302) [spring-boot-2.6.1.jar:2.6.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) [spring-boot-2.6.1.jar:2.6.1] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290) [spring-boot-2.6.1.jar:2.6.1] at com.starQeem.wohayp.WohaypApplication.main(WohaypApplication.java:19) [classes/:na] Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'fileServiceImpl': Bean with name 'fileServiceImpl' has been injected into other beans [fileServiceImpl] 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. at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:649) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1380) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:544) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:520) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:673) ~[spring-context-5.3.13.jar:5.3.13] at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:228) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119) ~[spring-beans-5.3.13.jar:5.3.13] at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:329) ~[spring-context-5.3.13.jar:5.3.13] ... 17 common frames omitted

Disconnected from the target VM, address: '127.0.0.1:59484', transport: 'socket'

Process finished with exit code 1

解决方案

加一层,新建一个新的类,将需要异步的方法写到这个类中,在fileServiceImpl中注入这个类

代码:

fileServiceImpl:

    @Resource
    private FileTransferService fileTransferService;
 /**
     * 上传文件
     *
     * @param userDto    用户dto
     * @param fileId     文件Id
     * @param file       文件
     * @param fileName   文件名称
     * @param filePid    文件pid
     * @param fileMd5    文件md5
     * @param chunkIndex 块索引
     * @param chunks     块
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public UploadResultDto uploadFile(UserDto userDto, String fileId, MultipartFile file, String fileName, String filePid, String fileMd5, Integer chunkIndex, Integer chunks) {
        ......
	     // 事务提交后调用异步方法
            TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
                @Override
                public void afterCommit() {
                    fileTransferService.transferFile(fileInfo.getFileId(), userDto);
                }
            });
       ......
	}

FileTransferService:

/**
 * @Date: 2023/5/31 22:38
 * @author: Qeem
 */
@Service
public class FileTransferService {

......

/**
 * 转码
 *
 * @param fileId  文件标识
 * @param userDto 用户dto
 */
@Async
@Transactional(rollbackFor = Exception.class)
public void transferFile(Long fileId, UserDto userDto) {
	......
}

}

问题解决,项目成功启动

end
SpringBoot

评论区

暂无评论