spring使用@Async注解异步处理
1. 何为异步调用?
在解释异步调用之前,我们先来看同步调用的定义;同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果。 异步调用则是只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕;而是继续执行下面的流程。例如, 在某个调用中,需要顺序调用 A, B, C三个过程方法;如他们都是同步调用,则需要将他们都顺序执行完毕之后,方算作过程执行完毕; 如B为一个异步的调用方法,则在执行完A之后,调用B,并不等待B完成,而是执行开始调用C,待C执行完毕之后,就意味着这个过程执行完毕了。
2. 常规的异步调用处理方式
在Java中,一般在处理类似的场景之时,都是基于创建独立的线程去完成相应的异步调用逻辑,通过主线程和不同的线程之间的执行流程,从而在启动独立的线程之后,主线程继续执行而不会产生停滞等待的情况。
3. @Async介绍
在Spring中,基于@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。
分为不带参数的异步调用;带参数的异步调用;调用返回Future的异步线程
4. @Async调用中的事务处理机制
在@Async标注的方法,同时也适用了@Transactional进行了标注;在其调用数据库操作之时,将无法产生事务管理的控制,原因就在于其是基于异步处理的操作。 那该如何给这些操作添加事务管理呢?可以将需要事务管理操作的方法放置到异步方法内部,在内部被调用的方法上添加@Transactional. 例如: 方法A,使用了@Async/@Transactional来标注,但是无法产生事务控制的目的。 方法B,使用了@Async来标注, B中调用了C、D,C/D分别使用@Transactional做了标注,则可实现事务控制的目的。
5. 配合使用@EnableAsync
@EnableAsync
在启动类或者Control类加上 @EnableAsync 注解
@EnableAsync注解的意思是可以异步执行,就是开启多线程的意思。可以标注在方法、类上。@Async所修饰的函数不要定义为static类型,这样异步调用不会生效
如下:
@SpringBootApplication
@EnableAsync
public class Application
{
public static void main( String[] args )
{
SpringApplication.run(Application.class, args);
}
}
或者:
@EnableAsync
@RestController
public class HelloController {
@Autowired
TestAsyncService testAsyncService;
}
6. 举例:
两张表:user_info和order_table 插入user_info数据时候用同步,插入order_table用异步。
在controller类中创建一个方法 同时保存user_info和order_table表。保存order_table用异步(对应service方法中用@Async标注)
(1)domain文件夹中创建Entity类
package com.cfj.ceshi.async.domain; import java.io.Serializable;
import java.util.Date; import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table; @Entity
@Table(name="order_table")
public class OrderTable implements Serializable { private static final long serialVersionUID = 1L; @Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id; @Column(name = "order_name")
private String orderName; @Column(name = "user_id")
private Integer userId; @Column(name = "create_date")
private Date createDate; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getOrderName() {
return orderName;
} public void setOrderName(String orderName) {
this.orderName = orderName;
} public Integer getUserId() {
return userId;
} public void setUserId(Integer userId) {
this.userId = userId;
} public Date getCreateDate() {
return createDate;
} public void setCreateDate(Date createDate) {
this.createDate = createDate;
} }
package com.cfj.ceshi.async.domain; import java.io.Serializable; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table; @Entity
@Table(name="user_info")
public class UserInfo implements Serializable { private static final long serialVersionUID = 1L; @Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String userName;
private String age;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "UserInfo [id=" + id + ", userName=" + userName + ", age=" + age + "]";
} }
(2)创建repository层操作数据库。如果是普通保存方法,只需要接口继承JpaRepository,不需要写具体方法
package com.cfj.ceshi.async.repository; import org.springframework.data.jpa.repository.JpaRepository; import com.cfj.ceshi.async.domain.OrderTable; public interface OrderRepository extends JpaRepository<OrderTable, Integer> { }
package com.cfj.ceshi.async.repository; import org.springframework.data.jpa.repository.JpaRepository; import com.cfj.ceshi.async.domain.UserInfo; public interface UserRepository extends JpaRepository<UserInfo, Integer> { }
(3)service层 其中order的实现层保存方法加上@Async
package com.cfj.ceshi.async.service; public interface OrderService { public void saveOrder(Integer UserId,String name); }
package com.cfj.ceshi.async.service; import java.util.List; import com.cfj.ceshi.async.domain.UserInfo; public interface UserService { public Integer save(UserInfo user); }
package com.cfj.ceshi.async.service.impl; import java.util.Date; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service; import com.cfj.ceshi.async.domain.OrderTable;
import com.cfj.ceshi.async.repository.OrderRepository;
import com.cfj.ceshi.async.service.OrderService; @Service
public class OrderServiceImpl implements OrderService { @Autowired
OrderRepository orderRepository; /**
* 异步保存
*/
@Async
@Override
public void saveOrder(Integer UserId,String name) {
System.out.println("UserId:"+UserId);
System.out.println("=====" + Thread.currentThread().getName() + "=========");
OrderTable orderTable = new OrderTable(); orderTable.setOrderName(name+"订单");
orderTable.setUserId(UserId);
orderTable.setCreateDate(new Date());
orderRepository.save(orderTable); } }
package com.cfj.ceshi.async.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import com.cfj.ceshi.async.domain.UserInfo;
import com.cfj.ceshi.async.repository.UserRepository;
import com.cfj.ceshi.async.service.UserService; @Service
@Transactional
public class UserServiceImpl implements UserService{ @Autowired
private UserRepository userRepository; @Override
public Integer save(UserInfo user) {
System.out.println("=====" + Thread.currentThread().getName() + "=========");
return userRepository.save(user).getId();
} }
(4) control层,control类中添加@EnableAsync注解
package com.cfj.ceshi.async.web; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import com.cfj.ceshi.async.domain.UserInfo;
import com.cfj.ceshi.async.service.OrderService;
import com.cfj.ceshi.async.service.UserService; @EnableAsync
@RestController
@RequestMapping("/tesasyc")
public class AsycWeb { @Autowired
UserService userService;
@Autowired
OrderService orderService; /**
* 请使用 postman测试 方式选择post http://localhost:8081/tesasyc/save-one
* body 中选择form-data 或者x-wwww-form-urlencoded 输入对应键值对
* @param name
* @param age
* @return
*/
@PostMapping(value = "/save-one") //相当于@RequestMapping(value = "/save-one", method = RequestMethod.POST)
public String postOne(String name,String age) {
UserInfo user = new UserInfo();
user.setUserName(name);
user.setAge(age);
Integer id = userService.save(user);
orderService.saveOrder(id,name);
return id.toString(); } }
参考:https://www.cnblogs.com/memoryXudy/p/7737418.html
https://segmentfault.com/a/1190000013974727
https://www.cnblogs.com/andyfengzp/p/6824253.html
https://www.cnblogs.com/benefitworld/p/5877423.html
spring使用@Async注解异步处理的更多相关文章
- Spring中@Async注解实现“方法”的异步调用
原文:http://www.cnblogs.com/zhengbin/p/6104502.html 简单介绍: Spring为任务调度与异步方法执行提供了注解支持.通过在方法上设置@Async注解,可 ...
- 使用Spring中@Async注解实现异步调用
异步调用? 在解释异步调用之前,我们先来看同步调用的定义:同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果. 异步调用则是只是发送了调用的指令,调用者无需等待被调用的方法完全执行完毕,继 ...
- Spring使用@Async注解
本文讲述@Async注解,在Spring体系中的应用.本文仅说明@Async注解的应用规则,对于原理,调用逻辑,源码分析,暂不介绍.对于异步方法调用,从Spring3开始提供了@Async注解,该注解 ...
- Spring使用@Async实现异步
使用场景 在实际项目中,一个接口如果需要处理很多数据,如果是同步执行,通过网络请求接口可能会出现请求超时.这时候就需要使用异步执行处理了. 使用经验 代码 异步服务类 @Service // Spri ...
- Spring @Async开启异步任务
1. 开启异步 @SpringBootApplication @EnableAsync //开启异步任务 public class Application { @Bean(name="pro ...
- 使用Spring的@Async创建异步方法
使用Spring的@Async创建异步方法 在开发系统的过程中,通常会考虑到系统的性能问题,提升系统性能的一个重要思想就是“串行”改“并行”.说起“并行”自然离不开“异步”,今天我们就来聊聊如何使用S ...
- 异步任务spring @Async注解源码解析
1.引子 开启异步任务使用方法: 1).方法上加@Async注解 2).启动类或者配置类上@EnableAsync 2.源码解析 虽然spring5已经出来了,但是我们还是使用的spring4,本文就 ...
- Spring异步-@Async注解
Spring异步:@Async注解 使用@Async前需要开启异步支持:@EnableAsync 注解和XML方式 @Async返回值的调用:需要使用Future包装 1.如果没有使用Future包装 ...
- spring boot @Async异步注解上下文透传
上一篇文章说到,之前使用了@Async注解,子线程无法获取到上下文信息,导致流量无法打到灰度,然后改成 线程池的方式,每次调用异步调用的时候都手动透传 上下文(硬编码)解决了问题. 后面查阅了资料,找 ...
随机推荐
- AngularJS实现数据列表的增加、删除和上移下移等功能实例
转: http://www.jb51.net/article/91991.htm 这篇文章给大家分享了AngularJS循环实现数据列表的增加.删除和上移下移等基础功能,对大家学习AngularJ ...
- Object-C(自学1)
----- 需求索要 自学了下 OBJECt-C ----- 就基础部分一些 和操作 command + R 运行command +B 只编译.m文件 NSlog() = printfNSLog 是 ...
- 【Python之路】特别篇--生成器(constructor)、迭代器(iterator)、可迭代对象(iterable)
生成器(constructor) 生成器函数在Python中与迭代器协议的概念联系在一起.包含yield语句的函数会被特地编译成生成器 !!! 当函数被调用时,他们返回一个生成器对象,这个对象支持迭代 ...
- 移动端布局Rem
一.最好用没有之一 http://www.jianshu.com/p/b00cd3506782 虽然博主说这个方案已经过期了 但是新方案还没有理解 就接着沿用这个 可以根据自己常用的设计稿的宽度修改 ...
- angular打包(三):pkg
希望打包成1个web服务,运行exe,启动 angular,供浏览器显示. 问题分析: 其实angular编译后,都是静态文件了.只需要打包express,让express可以以exe的形式运行就可以 ...
- Confluence 6 编辑一个附加文件的属性
你需要具有空间的 添加附件(Add Attachment)权限来编辑文件的属性. 希望编辑一个附加文件的属性: Go to > Attachments 单击你希望编辑附件边上的 属性(Prop ...
- P2015 二叉苹果树,树形dp
P2015 二叉苹果树 题目大意:有一棵二叉树性质的苹果树,每一根树枝上都有着一些苹果,现在要去掉一些树枝,只留下q根树枝,要求保留最多的苹果数(去掉树枝后不一定是二叉树) 思路:一开始就很直接的想到 ...
- 【CUDA 基础】4.0 全局内存
title: [CUDA 基础]4.0 全局内存 categories: - CUDA - Freshman tags: - 全局内存 - CUDA内存模型 - CUDA内存管理 - 全局内存编程 - ...
- php写入文件来调试接口数据
$fp = fopen('write.txt', 'a+b'); //a+读写方式打开,将文件指针指向文件末尾.b为强制使用二进制模式. 如果文件不存在则尝试创建之. fwrite($fp, prin ...
- js基础----数组
1.数组如何定义 //第一种定义方法 var arr=[1,2,3,4]; //第二种定义方法 var arr=new Array(1,2,3,4); 两者没有任何区别,[]的性能可能略高,因为代码短 ...