@Async注解失效可能产生的原因及解决方案
Posted Tang.Mr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了@Async注解失效可能产生的原因及解决方案相关的知识,希望对你有一定的参考价值。
1.@Async注解失效可能产生的原因及解决方案
1.1.未开启异步配置
需要在SpringBoot启动类上添加@EnableAsync
注解
@SpringBootApplication
@EnableAsync//开启异步线程配置
public class AsyncDemoApplication {
public static void main(String[] args) {
SpringApplication.run(AsyncDemoApplication.class, args);
}
}
或者在异步线程池配置类中添加@EnableAsync
@Slf4j
@EnableAsync
@Configuration
public class AsyncExecutorConfig implements AsyncConfigurer {
@Value("${spring.async-executors.core-size}")
private String CORE_SIZE;
@Value("${spring.async-executors.max-size}")
private String MAX_SIZE;
@Value("${spring.async-executors.queue-size}")
private String QUEUE_SIZE;
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(Integer.parseInt(CORE_SIZE));
executor.setMaxPoolSize(Integer.parseInt(MAX_SIZE));
executor.setQueueCapacity(Integer.parseInt(QUEUE_SIZE));
executor.setThreadNamePrefix("Spring Async Executor-");
executor.setRejectedExecutionHandler(
(runnable, threadPoolExecutor) -> {
try {
threadPoolExecutor.getQueue().put(runnable);
} catch (InterruptedException e) {
log.info("Thread pool receives InterruptedException: " + e);
}
});
executor.initialize();
return executor;
}
}
server:
port: 9081
spring:
async-executors:
core-size: 100
max-size: 200
queue-size: 500
1.2.异步方法和调用者方法在同一个内中
前置条件开启了异步注解:
例如:
@Slf4j
@SpringBootTest
class AsyncDemoApplicationTests {
@Test
void contextLoads() {
for (int i = 0; i < 10; i++) {
testMethod(i);
}
}
@Async
public void testMethod(Integer integer){
log.info("传入的参数为:"+integer);
}
}
运行测试方法后输出的结果:
2021-05-11 15:42:40.544 INFO 16020 --- [ main] com.tangling.AsyncDemoApplicationTests : 传入的参数为:0
2021-05-11 15:42:40.544 INFO 16020 --- [ main] com.tangling.AsyncDemoApplicationTests : 传入的参数为:1
2021-05-11 15:42:40.544 INFO 16020 --- [ main] com.tangling.AsyncDemoApplicationTests : 传入的参数为:2
2021-05-11 15:42:40.544 INFO 16020 --- [ main] com.tangling.AsyncDemoApplicationTests : 传入的参数为:3
2021-05-11 15:42:40.544 INFO 16020 --- [ main] com.tangling.AsyncDemoApplicationTests : 传入的参数为:4
2021-05-11 15:42:40.544 INFO 16020 --- [ main] com.tangling.AsyncDemoApplicationTests : 传入的参数为:5
2021-05-11 15:42:40.544 INFO 16020 --- [ main] com.tangling.AsyncDemoApplicationTests : 传入的参数为:6
2021-05-11 15:42:40.545 INFO 16020 --- [ main] com.tangling.AsyncDemoApplicationTests : 传入的参数为:7
2021-05-11 15:42:40.545 INFO 16020 --- [ main] com.tangling.AsyncDemoApplicationTests : 传入的参数为:8
2021-05-11 15:42:40.545 INFO 16020 --- [ main] com.tangling.AsyncDemoApplicationTests : 传入的参数为:9
从输出结果就可以看出来异步注解没有生效,如果异步注解生效的话他输入的数字应该是乱序的。
1.3.为什么异步方法与调用者在同一个内中会失效
原因是:spring 在扫描bean的时候会扫描方法上是否包含@Async注解,如果包含,spring会为这个bean动态地生成一个子类(即代理类,proxy),代理类是继承原来那个bean的。此时,当这个有注解的方法被调用的时候,实际上是由代理类来调用的,代理类在调用时增加异步作用。然而,如果这个有注解的方法是被同一个类中的其他方法调用的,那么该方法的调用并没有通过代理类,而是直接通过原来的那个bean,所以就没有增加异步作用,我们看到的现象就是@Async注解无效。
1.4.解决办法
将异步方法按照业务统一抽取到对应的bean中,当外部需要使用时将该bean注入,然后调用bean中的异步方法
上述代码改写
异步方法工具类
@Slf4j
@Component
public class AsyncUtils {
@Async
public void testMethod(Integer integer){
log.info("传入的参数为:"+integer);
}
}
测试类
@Slf4j
@SpringBootTest
class AsyncDemoApplicationTests {
@Autowired
private AsyncUtils asyncUtils;
@Test
void contextLoads() {
for (int i = 0; i < 10; i++) {
asyncUtils.testMethod(i);
}
}
}
运行输出结果
2021-05-11 15:56:11.624 INFO 18424 --- [sync Executor-1] com.tangling.utils.AsyncUtils : 传入的参数为:0
2021-05-11 15:56:11.624 INFO 18424 --- [ync Executor-10] com.tangling.utils.AsyncUtils : 传入的参数为:9
2021-05-11 15:56:11.624 INFO 18424 --- [sync Executor-8] com.tangling.utils.AsyncUtils : 传入的参数为:7
2021-05-11 15:56:11.624 INFO 18424 --- [sync Executor-9] com.tangling.utils.AsyncUtils : 传入的参数为:8
2021-05-11 15:56:11.624 INFO 18424 --- [sync Executor-6] com.tangling.utils.AsyncUtils : 传入的参数为:5
2021-05-11 15:56:11.624 INFO 18424 --- [sync Executor-5] com.tangling.utils.AsyncUtils : 传入的参数为:4
2021-05-11 15:56:11.625 INFO 18424 --- [sync Executor-3] com.tangling.utils.AsyncUtils : 传入的参数为:2
2021-05-11 15:56:11.625 INFO 18424 --- [sync Executor-2] com.tangling.utils.AsyncUtils : 传入的参数为:1
2021-05-11 15:56:11.624 INFO 18424 --- [sync Executor-4] com.tangling.utils.AsyncUtils : 传入的参数为:3
2021-05-11 15:56:11.624 INFO 18424 --- [sync Executor-7] com.tangling.utils.AsyncUtils : 传入的参数为:6
以上是关于@Async注解失效可能产生的原因及解决方案的主要内容,如果未能解决你的问题,请参考以下文章
Spring中异步注解@Async的使用原理及使用时可能导致的问题