目录
1.问题
今天解决了一个规范问题,代码中有一个地方使用了Thread直接起了一个异步现场,要改成放进公共线程
***************************
APPLICATION FAILED TO START
***************************
Description:
The dependencies of some of the beans in the application context form a cycle:
org.springframework.scheduling.annotation.ProxyAsyncConfiguration
↓
asyncConfig defined in file [***********\config\AsyncConfig.class]
↓
myAsyncExceptionHandler defined in file [***********\config\MyAsyncExceptionHandler.class]
┌─────┐
| oldServiceImpl defined in file [***********\service\Impl\OldServiceImpl.class]
↑ ↓
| asyncServiceImpl (field private ***********.service.OldService ***********.service.Impl.AsyncServiceImpl.oldService)
└─────┘
那好,我第一步就把下面<原代码>部分改成<问题代码>
然后就启动报错了,报错内容就是循环依赖
UnsatisfiedDependencyException
BeanCurrentlyInCreationException
我想我没使用构造器啊,用@Autowired了Spring不是可以解决循环依赖吗
~
2.分析原因
那我就看一下源码,网上找一下有没有类似的问题
2.1 为什么使用@Autowired后还出现循环依赖报错
带有@Transactional和@Async的循环依赖问题
跟代码看完可知,一个类有同时有循环依赖和** @Async **的情况时,会生成两个不同的代理对象,一个是异步的代理对象,就会导致代码在AbstractAutowireCapableBeanFactory.doCreateBean方法中直接抛出错误
2.2 注解在属性上的@Lazy如何解决循环依赖
跟着源码看了一下,核心意思就是在Spring初始化ioc容器时,使用@Lazy的属性可以不加载,这样启动不报错,运行时再加载
~
3.解决
我使用了方案一,就把下面<问题代码>部分改成<正确代码>
3.1 方案一 使用属性注入时添加@Lazy延时加载
在其中一个@Autowired加了@Lazy就可以了,那么在Spring首次填充属性populateBean时,可以忽略被@Lazy注解的属性,后面使用的时候再注入
3.2 方案二 把allowRawInjectionDespiteWrapping设置为true
@Component
public class FlagChange implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
((AbstractAutowireCapableBeanFactory) beanFactory).setAllowRawInjectionDespiteWrapping(true);
}
}
但是这样会导致@Async失效,因为就想分析原因里写的,两个不同的对象变成同一个了
3.3 方案三 使用AopContext.currentProxy调用本类方法
AopContext.currentProxy()可以,也可以自己走一下代理创建
~
4.代码
4.1 原代码
@Service
public class OldService {
public void initHandler(){
new Thread(() -> hanlder()).start();
}
public void hanlder(){
}
}
4.2 问题代码
@Service
public class OldService {
@Autowired
private AsyncService asyncService;
public void initHandler(){
asyncService.asyncHandler();
}
public void hanlder(){
}
}
@Service
public class AsyncService {
@Autowired
private OldService oldService;
@Async
public void asyncHandler(){
oldService.hanlder
}
}
4.3正确代码
@Service
public class OldService {
@Autowired
@Lazy
private AsyncService asyncService;
public void initHandler(){
asyncService.asyncHandler();
}
public void hanlder(){
}
}
@Service
public class AsyncService {
@Autowired
private OldService oldService;
@Async
public void asyncHandler(){
oldService.hanlder
}
}
参考
带有@Transactional和@Async的循环依赖问题
使用@Async异步注解导致该Bean在循环依赖时启动报BeanCurrentlyInCreationException异常的根本原因分析,以及提供解决方案
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/93731.html