SpringBoot使用Async注解失效原因分析及解决(spring异步回调)

目录
  • Async注解失效原因分析及解决(spring异步回调)
    • Spring中@Async
    • 有时候在使用的过程中@Async注解会失效
    • 解决方式一
    • 解决方式二
  • springboot @Async 失效可能原因

Async注解失效原因分析及解决(spring异步回调)

Spring中@Async

在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的;但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3.x之后,就已经内置了@Async来完美解决这个问题

有时候在使用的过程中@Async注解会失效

(原因和@Transactional注解有时候会失效的原因一样)。

下面定义一个Service:

两个异步执行的方法test03()和test02()用来模拟项目中可能出现的耗时操作,然后test()方法调用这两个耗时的方法:

定义Controller:

执行方法,返回结果:

方法执行结果明显与我们的预期不符,方法的输出顺序表示了test02()和test03()两个异步方法居然同步执行了,也就是说@Aysnc注解失效了!

失效的原因是因为我们是在test()方法中直接调用的test02()和test03()方法,相当于是this.test02()和this.test03()调用的,也就是说真正调用test02()和test03()方法的是TestService对象本身调用的,而@Async和@Transactional注解本质使用的是动态代理,真正应该是TestService的代理对象调用test02()和test03()方法。其实Spring容器在初始化的时候Spring容器会将含有AOP注解的类对象“替换”为代理对象(简单这么理解),那么注解失效的原因就很明显了,就是因为调用方法的是对象本身而不是代理对象,因为没有经过Spring容器,那么解决方法也会沿着这个思路来解决。

网上有不少博客说解决方法就是将要异步执行的方法单独抽取成一个类,这样的确可以解决异步注解失效的问题,原理就是当你把执行异步的方法单独抽取成一个类的时候,这个类肯定是被Spring管理的,其他Spring组件需要调用的时候肯定会注入进去,这时候实际上注入进去的就是代理类了,其实还有其他的解决方法,并不一定非要单独抽取成一个类。

解决方式一

在TestService中通过上下文获取自己的代理对象调用异步方法

其实我们的注入对象都是从Spring容器中给当前Spring组件进行成员变量的赋值,由于TestService使用了AOP注解,那么实际上TestService在Spring容器中实际存在的是它的代理对象。

执行结果,异步方法异步执行了:

解决方式二

开启cglib代理,手动获取Spring代理类

在启动类上加上:

使用AopContext.currentProxy()获取当前代理类:

这里为了证明Spring容器中的对象就是当前代理类对象特地输出了一句话:

运行结果:

OK,问题完美解决!

application.properties配置如下:

#java.lang.IllegalStateException: Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.
# 增加@EnableAspectJAutoProxy
spring.aop.auto=true
#开启CGLIB代理
spring.aop.proxy-target-class=true

springboot @Async 失效可能原因

1、当前类中其他函数调用有 @Async 注解的函数

2、当前类中有多态,方法名相同

3、启动类未加@EnableAsync

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 解决SpringBoot中使用@Async注解失效的问题

    错误示例,同一个类中使用异步方法: package com.xqnode.learning.controller; import com.fasterxml.jackson.core.JsonProcessingException; import org.springframework.scheduling.annotation.Async; import org.springframework.web.bind.annotation.GetMapping; import org.springf

  • 详解springboot使用异步注解@Async获取执行结果的坑

    目录 一.引言 二.获取异步执行结果 1.环境介绍 2.错误的方式 3.正确方式 三.异步执行@Async注解 四.总结 一.引言 在java后端开发中经常会碰到处理多个任务的情况,比如一个方法中要调用多个请求,然后把多个请求的结果合并后统一返回,一般情况下调用其他的请求一般都是同步的,也就是每个请求都是阻塞的,那么这个处理时间必定是很长的,有没有一种方法可以让多个请求异步处理那,答案是有的. springboot中提供了很便利的方式可以解决上面的问题,那就是异步注解@Async.正确的使用该注

  • SpringBoot用@Async注解实现异步任务

    什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行. 如何实现异步调用? 多线程,这是很多人第一眼想到的关键词,没错,多线程就是一种实现异步调用的方式. 在非spring目项目中我们要实现异步调用的就是使用多线程方式,可以自己实现Runable接口或者集成Thread类,或者使用jdk1.5以上提供了的Executors线程池. StrngBoot中则提供了很方便的方式执行异步调

  • 深入理解Spring注解@Async解决异步调用问题

    序言:Spring中@Async 根据Spring的文档说明,默认采用的是单线程的模式的.所以在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的. 那么当多个任务的执行势必会相互影响.例如,如果A任务执行时间比较长,那么B任务必须等到A任务执行完毕后才会启动执行.又如在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring3.x之后,已经内置了@Async来完美解决这个问题. 1. 何为异步调用? 在解释之前,我们先来看二

  • SpringBoot使用Async注解失效原因分析及解决(spring异步回调)

    目录 Async注解失效原因分析及解决(spring异步回调) Spring中@Async 有时候在使用的过程中@Async注解会失效 解决方式一 解决方式二 springboot @Async 失效可能原因 Async注解失效原因分析及解决(spring异步回调) Spring中@Async 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3.x之后,就已

  • Spring MVC 注解自动扫描失效原因分析

    关于spring自动扫描,在控制层,采用注解配置@Controller,项目能够成功启动,且无任何报错.但是 在进行页面跳转时,并未进行相应的拦截,整个界面只能在默认界面 ,跳转报404,由于楼主初次尝试,在绕了一个大圈后,初步确认是在扫描时mvc控制器,并未成功,详情请看代码 <!-- 开启controller注解支持 --> <context:component-scan base-package="com.cjw.test.controller" use-def

  • 详解springboot通过Async注解实现异步任务及回调的方法

    目录 前言 什么是异步调用? 1. 环境准备 2. 同步调用 3. 异步调用 4. 异步回调 前言 什么是异步调用? 异步调用是相对于同步调用而言的,同步调用是指程序按预定顺序一步步执行,每一步必须等到上一步执行完后才能执行,异步调用则无需等待上一步程序执行完即可执行.异步调用可以减少程序执行时间. 1. 环境准备 在 Spring Boot 入口类上配置 @EnableAsync 注解开启异步处理.创建任务抽象类 AbstractTask,并实现三个任务方法 doTaskOne(),doTas

  • PHP Header失效的原因分析及解决方法

    在PHP中用header("location:test.php")进行跳转要注意以下几点: 1.location和":"号间不能有空格,否则会出错. 2.在用header前不能有任何的输出,包括include的页面中标签"?>"后不能有空格!! 3.header后的PHP代码还会被执行. 续: 问题:header函数前输入内容 一般来说在header函数前不能输出html内容,类似的还有setcookie() 和 session 函数,这些

  • 为什么不要使用 async void的原因分析

    问题 在使用 Abp 框架的后台作业时,当后台作业抛出异常,会导致整个程序崩溃.在 Abp 框架的底层执行后台作业的时候,有 try/catch 语句块用来捕获后台任务执行时的异常,但是在这里没有生效. 原始代码如下: public class TestAppService : ITestAppService { private readonly IBackgroundJobManager _backgroundJobManager; public TestAppService(IBackgro

  • JQuery Dialog对话框 不能通过Esc关闭的原因分析及解决办法

    背景:想通过Esc键关闭展示中的Dialog对话框,发现有些对话框可以,有些会失效. 原因分析: 1.对话框上可以输入内容的标签元素可以,反之不行. 2.如果鼠标点击对话框后,也可以Esc键关闭. 可以看出对话框上是需要聚焦就可以了. 解决方案: 方案一: focus:function(){ $("#id").focus(); } 方案二: 延迟聚焦 setTimeout(function() { $("#id").focus(); }, 500); 以上所述是小编

  • SpringBoot Shiro 权限注解不起作用的解决方法

    最近在学习springboot结合shiro做权限管理时碰到一个问题. 问题如下: 我在userRealm中的doGetAuthorizationInfo方法中给用户添加了权限,然后在Controller中写了下面的代码.其中URL为/listArticle的方法必须要有article:over权限才能通过.我在doGetAuthorizationInfo方法中给该用户添加的权限并没有article:over,但是当前端向该URL发送请求时,@RequiresPermissions注解不起作用,

  • MySQL定时任务不能正常执行的原因分析及解决方法

    目录 前言 原因分析及解决方法 让定时任务快速执行 总结 前言 在使用数据库定时任务时,常常会出现定时任务不执行的问题,现对该问题出现的原因及解决方案做一些分析和整理. 原因分析及解决方法 当我们发现MySQL的定时任务没有执行时,首先去定时任务中查看[上次运行]时间是否正确,判断其是否正常执行,如果正常执行则需要考虑是否是事件逻辑不正确. 如果上次运行时间为空或者不正确,则需要查看数据库是否打开了定时任务,通过执行下列查询语句进行查询 show VARIABLES like '%event_s

随机推荐