对于一些简单的场景而言,其实spring的异步注解就非常好用.
本篇以SpringBoot项目为讲解:
一、生效步骤
1)配置@EnableAsync到启动类上
@EnableAsync
public class Application extends WebMvcConfigurationSupport {
2)在需要异步的方法或者某个类上配置@Async
2.1 注入到类上,该类的全部方法在其他地方调用都会是异步
@Service
@Async
public class AsyncService {
public void asyncSleep2() {
System.out.println("次线程2 " + Thread.currentThread().getName());
System.out.println("次线程2 开始异步休眠3秒");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("次线程2 异步休眠休眠结束");
}
public void asyncSleep1() {
System.out.println("次线程1 " + Thread.currentThread().getName());
System.out.println("次线程1 开始异步休眠3秒");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("次线程1 异步休眠休眠结束");
}
}
2.2 注入到方法上,当被其他调用,则会异步
@Async
public void asyncSleep2() {
System.out.println("次线程2 " + Thread.currentThread().getName());
System.out.println("次线程2 开始异步休眠3秒");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("次线程2 异步休眠休眠结束");
}
二、同类可以实现异步吗?
用this肯定是不可行的,那我本类里注入一个本Service,可以实现吗?答案也是不可以的,项目都没办法启动,错误如下:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'async1Controller': Unsatisfied dependency expressed through field 'asyncService'; nested exception is
org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'asyncSayService1': Bean with name 'asyncSayService1' has been injected into other beans [asyncSayService1]
in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean.
This is often the result of over-eager type matching - consider using 'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.
三、接口和实现类,该如何配置异步注解?
有实现类继承接口的形式,可以实现异步吗?
答案也是不可行的,可自行测试。
四、demo测试
public Integer getAsyncHello1() {
System.out.println("getAsyncHello1-Start 主线程1:"+Thread.currentThread().getName());
asyncService.asyncSleep1();
System.out.println("getAsyncHello1-End");
return 1;
}
asyncSleep1是一个异步方法,我将注解配置到了类上,就代表着我这个类里的所有方法都是需要异步实现的。
public void asyncSleep1() {
System.out.println("次线程1 " + Thread.currentThread().getName());
System.out.println("次线程1 开始异步休眠3秒");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("次线程1 异步休眠休眠结束");
}
如果asyncSleep1异步的话,那么如上我们应该打印出getAsyncHello1主线程的两个输出,然后再打印次线程的输出,并且我们通过输出可以看到线程名也不一样,就证明是开启了两个线程
简简单单的两个注解,就实现了异步操作。下篇讲述原理,从根源来了解实现。