让Spring的定时任务支持Kotlin挂起函数

kuku 发布于 22 天前 1 次阅读


SpringBoot3.2已原生支持

spring自带定时任务不支持运行kotlin挂起函数,会提示定时任务方法仅运行没有方法参数的异常

1、取消@EnableScheduling注解 在主类上面不需要加这个注解

2、重写ScheduledAnnotationBeanPostProcessorcreateRunnable方法

让其验证方法,运行有无参数的kotlin的挂起函数,其方法会返回一个Runnable的子类,在执行目标方法时也应该换成kotlin反射

class MyScheduledMethodRunnable(target: Any, method: Method): ScheduledMethodRunnable(target, method) {
    override fun run() {
        try {
            ReflectionUtils.makeAccessible(method)
            runBlocking {
                method.kotlinFunction?.callSuspend(target)
            }
        } catch (ex: InvocationTargetException) {
            ReflectionUtils.rethrowRuntimeException(ex.targetException)
        } catch (ex: IllegalAccessException) {
            throw UndeclaredThrowableException(ex)
        }
    }
}
class MyScheduledAnnotationBeanPostProcessor: ScheduledAnnotationBeanPostProcessor() {

    override fun createRunnable(target: Any, method: Method): Runnable {
        val parameters = method.parameters
        Assert.isTrue(
            parameters.isEmpty() || ((parameters.size == 1) && (parameters[0].type == Continuation::class.java)),
            "Only no-arg methods may be annotated with @Scheduled");
        val invocableMethod = AopUtils.selectInvocableMethod(method, target.javaClass)
        return MyScheduledMethodRunnable(target, invocableMethod)
    }

}

3、把重写的类放进Spring容器中

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
class ScheduledSuspendConfig {

    @Bean(name = [TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME])
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    fun scheduledAnnotationBeanPostProcessor(): ScheduledAnnotationBeanPostProcessor {
        return MyScheduledAnnotationBeanPostProcessor()
    }

}
此作者没有提供个人介绍。
最后更新于 2025-09-23