Spring Async 技术疑问:为何Autowired注入的实例可触发异步线程,new关键字创建的实例却无法实现?
为什么@Async在@Autowired实例和new实例上表现不同?
这个问题的核心其实和Spring的AOP代理机制直接相关,咱们一步步拆解背后的原因:
1. @Autowired注入的实例:Spring代理在起作用
当你通过@Autowired注入TestService时,你拿到的并不是TestServiceImpl的原始对象,而是Spring为它生成的动态代理对象。
Spring在启动时,会扫描到带有@Async注解的方法,并且为对应的Bean创建代理。当你调用asyncTask()方法时,代理会先拦截这个调用,然后把方法逻辑交给Spring的异步任务执行器(默认是SimpleAsyncTaskExecutor),由执行器创建新线程去执行方法内容,这就是你看到的异步效果。
你可以打印一下注入实例的类型验证这点:
System.out.println(testService.getClass()); // 输出会类似:com.sun.proxy.$ProxyXX 或者 TestServiceImpl$$EnhancerBySpringCGLIB$$XXXX
2. new关键字创建的实例:脱离Spring容器管理
用new TestServiceImpl()创建的对象,完全是普通的Java对象,没有被Spring容器接管。Spring根本不知道这个实例的存在,自然不会为它生成代理,也不会对@Async注解做任何处理。
这时候调用asyncTask()就是普通的方法调用,直接在当前线程同步执行,不会触发任何Spring的异步逻辑。同样打印类型就能看出来:
TestService newService = new TestServiceImpl(); System.out.println(newService.getClass()); // 输出就是原始的:com.example.demo.TestServiceImpl
额外补充:@Async生效的必要前提
要让@Async正常工作,还有两个关键前提:
- 项目中已经通过
@EnableAsync注解启用了Spring的异步支持 - 带有
@Async方法的类必须是Spring管理的Bean(比如标注了@Service、@Component等注解)
内容的提问来源于stack exchange,提问作者sleepy
相关产品推荐
相关产品推荐

