外观
一句话答案
@Async 通过 AOP 代理将方法提交到线程池异步执行,必须自定义线程池避免默认的 SimpleAsyncTaskExecutor 无限创建线程。
核心要点
| 维度 | Spring Framework | Spring Boot | Spring Cloud |
|---|---|---|---|
| 定位 | Java 企业级应用基础框架(IoC/AOP) | Spring 的快速启动脚手架 | 微服务架构的一站式解决方案 |
| 核心价值 | IoC 容器、AOP、事务管理 | 自动配置、内嵌 Tomcat、起步依赖 | 服务发现、配置中心、链路追踪、熔断限流 |
| 配置方式 | XML / 注解(较繁琐) | 约定大于配置(开箱即用) | 注解 + 配置中心(统一管理) |
| 部署方式 | WAR 包,外部 Tomcat | JAR 包,内嵌 Tomcat/Jetty,直接运行 | JAR 包,注册到服务注册中心 |
| 依赖关系 | 基础 | 基于 Spring Framework,简化开发 | 基于 Spring Boot,扩展为微服务 |
| 关键技术 | BeanFactory、ApplicationContext | starter、AutoConfiguration | Eureka/Nacos、Feign、Ribbon、Hystrix/Sentinel、Sleuth、Gateway |
关系比喻:
- Spring Framework = 发动机(提供基础能力)
- Spring Boot = 整车装配(加上车身、座椅,可以直接开)
- Spring Cloud = 车队管理系统(多辆车的调度、通信、监控)
追问与易错
追问方向:
- 不配线程池会怎样?
- 异步方法返回值怎么获取?
- 异步方法异常去哪了?
易错点:
- ❌ @Async 加在 private 方法——无效
- ❌ 同类内部调用也能异步——不经过代理失效
💡 记忆锚点
@Async = AOP代理把方法丢进线程池异步跑。两大坑必记:不配线程池会用SimpleAsyncTaskExecutor(每次new线程,生产必炸);同类内部调用不走代理所以失效(和@Transactional自调用失效同理)。