什么是循环依赖?
循环依赖(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) {
......
}
}
问题解决,项目成功启动
评论区