@Async:由Spring提供,被标记的函数转为异步执行;使用不当则无法达到预期效果,本文主要针对添加注解无效的情况进行分析。
@Service
public class TestService{
public void test(){
System.out.println("TestService.test() start");
testAsync();
System.out.println("TestService.test() end");
}
@Async
public void testAsync(){
System.out.println("TestService.testAsync() start");
Thread.sleep(3000);
System.out.println("TestService.testAsync() end");
}
}
//在外部类调用test()
//执行到testAsync()时没有异步处理
//在外部类调用testAsync()
//执行到testAsync()时异步处理
结论:
@Async注解本质上使用的是动态代理;
Spring在容器初始化的时候会将含有AOP注解的类对象替换为代理对象;
外部类调用含有AOP注解的函数时,走代理对象执行异步处理逻辑达到异步效果;
test()调用testAsync()时是自己直接调用自己,没有通过代理类,所以无效。
常用的AOP注解还有@Transactional,使用时无效也可能是如上原因导致
解决方案:
1.采用如上方式,通过外部类调用
//2.在test()中获取自己的代理类,通过代理类执行testAsync();
@Service
public class TestService{
public void test(){
System.out.println("TestService.test() start");
TestService proxy=SpringUtil.getBean(TestService.class);
proxy.testAsync();
System.out.println("TestService.test() end");
}
@Async
public void testAsync(){
System.out.println("TestService.testAsync() start");
Thread.sleep(3000);
System.out.println("TestService.testAsync() end");
}
}
//3.开启cglib代理,手动获取代理
//...其他注解省略
@EnableAsync
@EnableAspectJAutoProxy(exposeProxy=true)
public class TestApplication{
//...内容省略
}
@Service
public class TestService{
public void test(){
System.out.println("TestService.test() start");
TestService proxy=AopContext.currentProxy();
proxy.testAsync();
System.out.println("TestService.test() end");
}
@Async
public void testAsync(){
System.out.println("TestService.testAsync() start");
Thread.sleep(3000);
System.out.println("TestService.testAsync() end");
}
}