zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    同步请求和异步请求的区别
    Ajax初步理解
    ajax的GET和POST请求
    What's this?(js)
    rxjs
    Angular7_获取异步方法里面的数据
    Angular7_人员登记系统
    Angular7
    特殊操作符
    Oracle 表操作
  • 原文地址:https://www.cnblogs.com/kxm87/p/9290285.html
Copyright © 2011-2022 走看看