简述
异步调用 对应的是 同步调用,同步调用 指程序按照 定义顺序 依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行;异步调用 指程序在顺序执行时,不等待 异步调用的语句 返回结果 就执行后面的程序。
在平常的开发中,为了使用异步编程,开发者一般都是通过手动多线程实现。但Spring Boot 为了简化开发流程,提供了异步编程注解@Async。只要是在对应的方法上加入注解就可以实现异步调用。
@Async使用
在启动的Application中加入@EnableAsync
@EnableAsync
@SpringBootApplication
public class CrmToolApplication {
public static void main(String[] args) {
SpringApplication.run(CrmToolApplication.class, args);
}
}
在需要异步调用的方法上加入@Async
@Service
@Slf4j
public class TestService {
@Async
public void asyncMethodWithNoReturnType() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("Async...{}", this.getClass().getSimpleName());
}
}
@Async注解原理分析
看下@EnableAsync注解的源码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({AsyncConfigurationSelector.class})
public @interface EnableAsync {
Class
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default 2147483647;
}
mode默认值AdviceMode.PROXY,此值含义是使用AOP实现。AOP的本质就是动态代理,动态代理的局限在同一个类中是无法实现调用。
实例
@Component
@Order(1)
@Slf4j
public class StartRunner1 implements ApplicationRunner {
private final TestService testService;
public StartRunner1(TestService testService) {
this.testService = testService;
}
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("run ---- {}", this.getClass().getSimpleName());
Thread.sleep(1000);
// testService.asyncMethodWithNoReturnType();
asyncMethodWithNoReturnType();
}
@Async
public void asyncMethodWithNoReturnType() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("Async...{}", this.getClass().getSimpleName());
}
}
默认情况下上面的@Async无法生效。
2020-07-18 09:09:17.269 [restartedMain] INFO c.c.t.s.StartRunner1 | 31 | - run ---- StartRunner1
2020-07-18 09:09:21.290 [restartedMain] INFO c.c.t.s.StartRunner1 | 46 | - Async...StartRunner1
切换至调用TestService中的异步方法
2020-07-18 09:10:17.464 [restartedMain] INFO c.c.t.s.StartRunner1 | 31 | - run ---- StartRunner1
2020-07-18 09:10:18.472 [restartedMain] INFO c.c.t.s.StartRunner2 | 24 | - run ---- StartRunner2
2020-07-18 09:10:21.492 [task-1] INFO c.c.t.s.TestService | 38 | - Async...TestService
可以看出执行的 线程发生了变化。(restartedMain,task-1)
总结
@Async 注解没生效一般问题的就是在同一类内调用,Spring 的很多注解默认都是使用AOP实现,而AOP的本身就是在同一个类中无法调用,故此通过其实现的注解也是无法同类之内使用。
领取专属 10元无门槛券
私享最新 技术干货