SpringBoot2.3中@Async实现异步

启动加上@EnableAsync ,需要执行异步方法上加入@Async。
在方法上加上@Async之后 底层使用多线程技术。

不使用异步

先关代码:

package com.yiyang.myfirstspringdemo.controller;

import com.yiyang.myfirstspringdemo.service.HelloService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
@Slf4j
public class HelloController {

    @Resource
    private HelloService helloService;

    @GetMapping("/helloAsync")
    public String helloAsync() {
        log.info("1");
        helloService.addHello();
        log.info("4");
        return "hello world ==== async";
    }
}
package com.yiyang.myfirstspringdemo.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Author 刘翊扬
 * @Date 2020/10/3 3:14 下午
 * @Version 1.0
 */
@Service
@Slf4j
public class HelloService {

    public void addHello() {
        log.info("2");
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("3");
    }

}

不使用异步处理。
正常输出的顺序:1 2 3 4

2020-10-03 15:49:41,174  INFO HelloController:24 - 1
2020-10-03 15:49:41,175  INFO HelloService:22 - 2
2020-10-03 15:49:43,182  INFO HelloService:29 - 3
2020-10-03 15:49:43,182  INFO HelloController:26 - 4
2020-10-03 15:49:43,185  INFO LogAspect:51 - RESPONSE : hello world ==== async

使用异步

在addHello()方法上面加上@Async

同时,启动类上开启异步调用

package com.yiyang.myfirstspringdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;

@SpringBootApplication(scanBasePackages = {"com.yiyang.myfirstspringdemo"})
//@SpringBootApplication
@EnableAsync // 开启异步调用
public class MyFirstSpringDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyFirstSpringDemoApplication.class, args);
    }

}

再次访问,结果是:1 4 2 3

2020-10-03 15:52:52,660  INFO HelloController:24 - 1
2020-10-03 15:52:52,666  INFO HelloController:26 - 4
2020-10-03 15:52:52,675  INFO HelloService:23 - 2
2020-10-03 15:52:52,675  INFO LogAspect:51 - RESPONSE : hello world ==== async
2020-10-03 15:52:54,681  INFO HelloService:30 - 3

注意:在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解会失效

例如:
改造HelloService

package com.yiyang.myfirstspringdemo.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
 * @Author 刘翊扬
 * @Date 2020/10/3 3:14 下午
 * @Version 1.0
 */
@Service
@Slf4j
public class HelloService {

    public void addHello() {
        log.info("2");
        sendMessage();
        log.info("3");
    }

    @Async
    public void sendMessage() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("发送消息!!!!!");
    }
}

访问结果是:1 2 3 4

2020-10-03 15:55:51,449  INFO HelloController:24 - 1
2020-10-03 15:55:51,585  INFO HelloService:17 - 2
2020-10-03 15:55:53,595  INFO HelloService:29 - 发送消息!!!!!
2020-10-03 15:55:53,596  INFO HelloService:19 - 3
2020-10-03 15:55:53,598  INFO HelloController:26 - 4
2020-10-03 15:55:53,599  INFO LogAspect:51 - RESPONSE : hello world ==== async

解决办法。。。。。。

讲sendMessage()方法放到别的类里面。

新建SendMessageService类

package com.yiyang.myfirstspringdemo.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
 * @Author 刘翊扬
 * @Date 2020/10/3 3:37 下午
 * @Version 1.0
 */
@Service
@Slf4j
public class SendMessageService {

    @Async
    public void sendMessage() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("发送消息!!!!!");
        log.info("5");
    }
}

修改HelloService的内容

package com.yiyang.myfirstspringdemo.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @Author 刘翊扬
 * @Date 2020/10/3 3:14 下午
 * @Version 1.0
 */
@Service
@Slf4j
public class HelloService {

    @Resource
    private SendMessageService sendMessage;

    public void addHello() {
        log.info("2");
        sendMessage.sendMessage();
        log.info("3");
    }
}

访问结果是:1 2 3 4 5

2020-10-03 16:00:30,870  INFO HelloController:24 - 1
2020-10-03 16:00:30,871  INFO HelloService:22 - 2
2020-10-03 16:00:30,875  INFO HelloService:24 - 3
2020-10-03 16:00:30,891  INFO HelloController:26 - 4
2020-10-03 16:00:30,901  INFO LogAspect:51 - RESPONSE : hello world ==== async
2020-10-03 16:00:32,889  INFO SendMessageService:23 - 发送消息!!!!!
2020-10-03 16:00:32,890  INFO SendMessageService:24 - 5

那么为什么,在同一类中一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解会失效呢????

看这个博客:https://blog.csdn.net/clementad/article/details/47339519

posted @ 2020-10-03 16:44  刘翊扬  阅读(363)  评论(0编辑  收藏  举报