SpringBoot3.2已原生支持
spring
自带定时任务不支持运行kotlin
挂起函数,会提示定时任务方法仅运行没有方法参数的异常
1、取消@EnableScheduling
注解
在主类上面不需要加这个注解
2、重写ScheduledAnnotationBeanPostProcessor
的createRunnable
方法
让其验证方法,运行有无参数的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()
}
}