@Async注解导致循环依赖,BeanCurrentlyInCreationException异常

使用@Async异步注解导致该Bean在循环依赖时启动报BeanCurrentlyInCreationException异常的根本原因分析,以及提供解决方案

 

今天在自己项目中使用@Async的时候,碰到了一个问题:Spring循环依赖(circular reference)问题
或许刚说到这,有的小伙伴就会大惊失色了。Spring不是解决了循环依赖问题吗,它是支持循环依赖的呀?怎么会呢?

出现使用@Async导致循环依赖问题的必要条件:

  1. 已开启@EnableAsync的支持
  2. @Async注解所在的Bean被循环依赖了

为什么有小伙伴跟我说:我使用@Async即使本类方法调用也从来木有遇到这个错误啊?难道它不常见?
为此经过我的一番调查,包括看一些同事、小伙伴的代码发现:并不是使用@Async没有启动报错,而是他本类调用的时候直接调用的方法,这样@Async是不生效的但小伙伴却全然不知而已。

至于@Async没生效这种问题为何没报出来???甚至过了很久很久都没人发现和关注??
其实道理很简单,它和事务不生效不一样,@Async若没生效99%情况下都不会影响到业务的正常进行,因为它不会影响数据正确性,只会影响到性能(无非就是异步变同步呗,这是兼容的)

我们知道事务不生效和@Async不生效的根本原因都是同一个:直接调用了本类方法而非接口方法/代理对象方法。
解决这类不生效问题的方案一般我们都有两种:

自己注入自己,然后再调用接口方法(当然此处的一个变种是使用编程方式形如:AInterface a = applicationContext.getBean(AInterface.class);这样子手动获取也是可行的~~~本文不讨论这种比较直接简单的方式)
使用AopContext.currentProxy();

让不调用本类的@Async方法不就可以了;让不产生循环依赖不就可以了,这也是解决方案

1:新建一个线程池配置类AsyncConfig

@EnableAsync
@Configuration
public class AsyncConfig implements AsyncConfigurer {@Overridepublic Executor getAsyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(10); //核心线程数executor.setMaxPoolSize(20);  //最大线程数executor.setQueueCapacity(1000); //队列大小executor.setKeepAliveSeconds(300); //线程最大空闲时间executor.setThreadNamePrefix("fsx-Executor-"); //指定用于新创建的线程名称的前缀。executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 拒绝策略(一共四种,此处省略)executor.initialize();return executor;}// 异常处理器:当然你也可以自定义的,这里我就这么简单写了~~~@Overridepublic AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {return new SimpleAsyncUncaughtExceptionHandler();}
}

 

 

2:新增一个HelloService接口

public interface HelloService {Object hello(Integer id);void fun1();
}

 

3:新增一个HelloServiceImpl实现类

@Service
public class HelloServiceImpl implements HelloService{@Autowiredprivate HelloService helloService;@Overridepublic Object hello(Integer id) {System.out.println("线程名称:" + Thread.currentThread().getName());helloService.fun1(); // 使用接口方式调用,而不是thisreturn "service hello";}@Async@Overridepublic void fun1() {System.out.println("线程名称:" + Thread.currentThread().getName());}
}

 

4:新增一个异步测试类

@SpringBootTest
public class AsyncTest {@Autowiredprivate HelloService helloService;@Testpublic void test(){helloService.hello(1);}
}

 

5:启动测试类

此种做法首先是Spring中一个典型的循环依赖场景:自己依赖自己。本以为能够像解决事务不生效问题一样依旧屡试不爽,但没想到非常的不给面子,启动即报错

报错如下BeanCurrentlyInCreationException异常

 

 

6:解决方法

在HelloServiceImpl类上@Autowired注解下加上@Lazy注解,即懒加载

 

7:启动项目

输出如下,成功了

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/269861.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

人工智能:图像数字化相关的知识介绍

❤️作者主页:IT技术分享社区 ❤️作者简介:大家好,我是IT技术分享社区的博主,从事C#、Java开发九年,对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️个人荣誉: 数据库领域优质创作者🏆&#x…

《深入理解Java虚拟机》读书笔记

堆分配参数: -XX:PrintGC 使用该参数,虚拟机启动后,只要遇到GC就会打印日志; -XX:UseSerialGC 配置串行回收器; -XX:PrintGCDeltails 可以查看详细信息,包括各个区的情况 -Xms&#…

线程可见性和关键字volatile

线程可见性 可以看到程序变量running没volatile是死循环 加了volatile成功输出 public class VolitaleTest {private static volatile boolean running true;public static void main(String[] args) {Thread thread new Thread(() ->{long i 0L;while (running){i;}Sys…

每秒钟承载600万订单级别的无锁并行计算框架 Disruptor学习

1.来源 Disruptor是英国外汇交易公司LMAX开发的一个高性能队列,研发的初衷是解决内部的内存队列的延迟问题,而不是分布式队列。基于Disruptor开发的系统单线程能支撑每秒600万订单,2010年在QCon演讲后,获得了业界关注。 2.应用背…

logisim输出变成红色的e_新车实拍解析 福特Mustang Mach-E亮点实拍图解

福特Mustang Mach-E新车主要针对造型设计对外进行了首次亮相发布,对新车内饰以及具体新车方面的数据信息暂未公布。如果消费者想要了解这款新车,大家可以继续关注《杨总继续观察》带来这款新车的详细报道。新车在设计上可以看作是一款福特野马的电动跨界…

castle windsor学习----- Services and Components 两者的定义

转载于:https://www.cnblogs.com/lanpingwang/p/6534208.html

html5 接收蓝牙广播_蓝牙定位技术浅析(化工厂应用)

蓝牙定位基于RSSI(Received Signal Strength Indication,信号场强指示)定位原理。根据定位端的不同,蓝牙定位方式分为网络侧定位和终端侧定位。由于蓝牙由于是近场通信其定位精度取决于点位的部署密度,一般会设计成7-8米一个定位基站&#xf…

catia如何整列加工_”模具加工“最全面的诠释,你真的都懂了吗?

1定义模具加工(Mold Making)是指成型和制坯工具的加工,此外还包括剪切模和模切模具。通常情况下,模具有上模和下模两部分组成。将钢板放置在上下模之间,在压力机的作用下实现材料的成型,当压力机打开时,就会获得由模具…

mysql中基本的DDL语句(关注一下,以后会继续更新喔!)

一.简单介绍sql 一.简单介绍sql (1)结构化查询语言(Structured Query Language,SQL)是一种有特殊目的的编程语言,也是一种数据库查询和一些程序设计语言,专用于存储及调用数据以及查询、更新和管理关系数…

[ST2017] Lab1: Triangle type and Junit test

Lab1 3014218071 王汉超 Request: Write a program with a function(getTriangleStatus) and test it, which takes three double number l1, l2, l3 as lengths of triangle sides and calculates whether the triangle is equilateral, isosceles, or scalene. Contents: 一.…

说说图片加载不出来_晒晒我的新家,朋友都说好看,恨不得天天宅在卧室不出来...

我和老婆是高中同学,早年因为没有考上大学,我早早的来北京闯事业,也吃了很多苦,好在那时机会很多,做什么都能赚点钱,生活质量也逐渐好了起来,配得上我老婆这样的大学生,今年和老婆结…

mysql中基本的DML语句

1.DML语句的含义 数据操纵语言(DML) 由 DBMS 提供,用于让用户或程序员使用,实现对数据库中数据的操作。基本的 DML 分为两类四种:检索(查询)和更新(插入、删除、修改)。…

委托窗体传值

转载于:https://www.cnblogs.com/yoyo-524/p/6538547.html

yy自动语音接待机器人_人脸签到、发言记录,会议机器人来啦

会议机器人来啦~~在各种关于会议的吐槽中,很多人产生了一个需求:会议机器人。对于这一需求,安泽智能基于自身在人工智能行业的经验,研发出了适用于会议场景,具有会场引导、人脸识别签到、会议记录、与主持人串讲互动等…

TimeUnit

TimeUnit TimeUnit.DAYS 表示天 TimeUnit.SECONDS表示 秒