【Java异步】解决@Async注解,同类下调用不生效
个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~
个人主页:.29.的博客
学习社区:进去逛一逛~
解决@Async注解,同类下调用不生效
- 一、@Async注解
- 基本使用
- 二、为什么同类下@Async不生效
- 根本原因
- 内部调用失效案例
- 三、解决方案
- 方式1 异步方法拆分到不同类
- 方式2 通过代理对象调用
一、@Async注解
@Async
是 Spring 框架中用于实现异步方法调用的注解
基本使用
1、启用异步支持 在配置类添加 @EnableAsync
@Configuration
@EnableAsync
public class AsyncConfig {}
2、标注异步方法,在需要异步的方法条件 @Async
@Service
public class EmailService {
@Async
public void sendAsyncEmail(String content) {
// 耗时操作(如发送邮件)
}
}
二、为什么同类下@Async不生效
根本原因
Spring 通过 动态代理 实现 @Async 的异步能力:
1、代理对象隔离
- 当调用被
@Async
注解的方法时,实际调用的是代理对象的方法 - 同类中的内部调用(如
this.method()
)直接访问原始对象,绕过了代理
2、代理类型差异
- 如果使用 JDK 动态代理(基于接口),同类调用无法触发代理逻辑
- 如果使用 CGLIB 代理(无接口类),同类调用同样受限于 this 调用
内部调用失效案例
@Service
public class OrderService {
// ✅ 外部调用有效
public void createOrder() {
sendAsyncMsg(); // 通过代理对象调用
}
// ❌ 同类调用无效
public void batchCreateOrders() {
this.sendAsyncMsg(); // 直接调用原始对象方法
}
@Async
public void sendAsyncMsg() {
// 异步发送消息
}
}
三、解决方案
方式1 异步方法拆分到不同类
// 异步操作单独成类
@Service
public class AsyncMessageService {
@Async
public void sendAsyncMsg() {
// 异步逻辑
}
}
// 主业务类通过依赖注入调用
@Service
@RequiredArgsConstructor
public class OrderService {
private final AsyncMessageService asyncMessageService;
public void batchCreateOrders() {
asyncMessageService.sendAsyncMsg(); // 通过代理对象调用
}
}
方式2 通过代理对象调用
- 配置类添加配置exposeProxy = true
@EnableAspectJAutoProxy(exposeProxy = true) // 配置类添加
@Configuration
@EnableAsync
public class AsyncConfig {}
- 同类下通过代理对象调用异步方法
@Service
public class OrderService {
//AopContext上下文获取当前代理对象,调用异步方法
public void batchCreateOrders() {
((OrderService) AopContext.currentProxy()).sendAsyncMsg();
}
@Async
public void sendAsyncMsg() {
// 异步逻辑
}
}