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()
    }

}
最后修改:2023 年 10 月 26 日
如果觉得我的文章对你有用,请随意赞赏