springboot中使用异步方法 CompletableFuture.runAsync导致的上下文缺失。

项目场景

项目场景:这是一个任务的下发接口,这个任务是个复杂的功能,涉及到多次调用外部接口,处理时长比较长,所以在下发接口做了一个异步。


问题描述

使用异步方法:

           CompletableFuture.runAsync(() -> {
				// todo something
            });

在该任务涉及到公司封装的定时任务管理类时,提示部分class 找不到。类似以下的报错。

Caused by: java.lang.ClassNotFoundException: aac.tt.abac.ScheduleTask
        at jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[?:?]
        at jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[?:?]
        at java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[?:?]
        at java.lang.Class.forName0(Native Method) ~[?:?]
        at java.lang.Class.forName(Class.java:495) ~[?:?]
        at java.lang.Class.forName(Class.java:474) ~[?:?]
        at org.springframework.util.ClassUtils.forName(ClassUtils.java:291) ~[spring-core-6.0.21.jar:6.0.21]
        at org.springframework.scheduling.quartz.ResourceLoaderClassLoadHelper.loadClass(ResourceLoaderClassLoadHelper.java:81) ~[spring-context-support-6.0.21.jar:6.0.21]
        at org.springframework.scheduling.quartz.ResourceLoaderClassLoadHelper.loadClass(ResourceLoaderClassLoadHelper.java:87) ~[spring-context-support-6.0.21.jar:6.0.21]
        at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.selectJobDetail(StdJDBCDelegate.java:852) ~[quartz-2.3.1.jar:?]
        at org.quartz.impl.jdbcjobstore.JobStoreSupport.retrieveJob(JobStoreSupport.java:1390) ~[quartz-2.3.1.jar:?]
        at org.quartz.impl.jdbcjobstore.JobStoreSupport.storeTrigger(JobStoreSupport.java:1210) ~[quartz-2.3.1.jar:?]
Caused by: org.quartz.JobPersistenceException: Couldn't retrieve job because a required class was not found:

原因分析

开始以为是未在启动类配置该包的扫描,但是检查了一遍发现都配了。

测试了一下不使用异步方法,发现不会报错了。
大概原因就是CompletableFuture.runAsync 异步方法导致spring应用上下文缺失,
后面查了一下相关资料:

Spring 管理的 Bean 中调用 CompletableFuture.runAsync 时,默认情况下,这个异步任务会在 ForkJoinPool.commonPool() 中执行,而不是在 Spring 应用上下文中。这意味着在这个新线程中,Spring 的依赖注入和 AOP 代理等特性将不可用


解决方案

  1. 可以新建一个线程来执行。
  2. 使用@Async注解
  3. 自定义 Executor:你可以创建一个自定义的 Executor 并将其配置为 Spring 的 TaskExecutor,这样可以确保在异步任务中仍然能够访问 Spring 的上下文。
@Configuration
public class AsyncConfig {

    @Bean
    public Executor taskExecutor() {
        return Executors.newFixedThreadPool(10);
    }
}

// 在你的服务类中使用自定义的 Executor
@Service
public class MyService {

    private final Executor executor;

    @Autowired
    public MyService(Executor executor) {
        this.executor = executor;
    }

    public void doSomethingAsync() {
        CompletableFuture.runAsync(() -> {
            // 异步任务
            System.out.println("Running in a separate thread with runAsync");
        }, executor);
    }
}
  1. 也许还有其他方法,可以提供给我,非常感谢。


若您有任何看法、疑问或补充,欢迎在下方留言区畅所欲言,我非常期待与您深入交流。您的评论将让这个话题更加丰富多彩。

如果这篇文章对您有长期参考价值,不妨点击收藏按钮,方便日后随时查阅。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SevenBean

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值