使用@Scheduled和@EnableScheduling但是给出NoSuchBeanDefinitionException

log*_*yer 23 java cron scheduled-tasks spring-4

我已经在线跟踪非常简单的示例在Spring中设置了一个cron作业但我每次都在我的Tomcat启动日志中不断收到此错误:

2015-05-25 00:32:58 DEBUG ScheduledAnnotationBeanPostProcessor:191 - 
Could not find default TaskScheduler bean org.springframework.beans.factory.NoSuchBeanDefinitionException: No 
qualifying bean of type [org.springframework.scheduling.TaskScheduler] is defined

2015-05-25 00:32:58 DEBUG ScheduledAnnotationBeanPostProcessor:202 - Could not    
find default ScheduledExecutorService bean
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying    
bean of type [org.springframework.scheduling.TaskScheduler] is defined
Run Code Online (Sandbox Code Playgroud)

并且用于实现cron的2个java类:

1)@Configuration类:

@Configuration
@EnableScheduling
public class ClearTokenStoreCronEnable {    
  final static Logger log =   
  LoggerFactory.getLogger(ClearTokenStoreCronEnable.class);
  private @Autowired TokenStoreRepository tokenStoreRepository; 
}
Run Code Online (Sandbox Code Playgroud)

和Cron工作班:

@Service
public class ClearTokenStoreWorkerService {

    final static Logger log = LoggerFactory.getLogger(ClearTokenStoreWorkerService.class);
    private @Autowired TokenStoreRepository tokenStoreRepository;

    //@Scheduled(fixedDelay=5000)
    //run daily at midnight
    @Scheduled(cron = "0 0 * * * *")
    public void tokenStoreTable() {
        log.debug("tokenstore table truncated - start");
        tokenStoreRepository.deleteAll();
        log.debug("tokenstore table truncated - end");
    }
}
Run Code Online (Sandbox Code Playgroud)

作为旁注,cron作业在午夜运行,但它似乎也在其他时间随机运行.不确定这是一个错误还是我的cron表达式错误: @Scheduled(cron = "0 0 * * * *")

我此时主要担心的是为什么我会收到ScheduledAnnotationBeanPostProcessor错误?它正在寻找TaskScheduler和ScheduledExectorService. 我只需要每天开一次.我没有进行任何并发处理或我需要多个线程.最终这些错误是有害的还是我需要修复它们?

小智 18

根据异常信息"无法找到默认的TaskScheduler bean",配置应该定义"TaskScheduler"而不是"Executor"

@Configuration
public class AppContext extends WebMvcConfigurationSupport {
    @Bean
    public TaskScheduler taskScheduler() {
        return new ConcurrentTaskScheduler();
    }

    // Of course , you can define the Executor too
    @Bean
    public Executor taskExecutor() {
        return new SimpleAsyncTaskExecutor();
   }
Run Code Online (Sandbox Code Playgroud)

}


xti*_*ian 16

编辑:最好的答案在这里,它涉及创建一个执行器:

@Configuration
@EnableAsync
public class AppContext extends WebMvcConfigurationSupport {
    @Bean
    public Executor taskExecutor() {
        return new SimpleAsyncTaskExecutor();
    }
}
Run Code Online (Sandbox Code Playgroud)

上一个(尽管仍然有效):

使用DEBUG严重性记录NoSuchBeanDefinitionException,可以安全地忽略它.如果查看ScheduledAnnotationBeanPostProcessor的源代码,您会看到它首先尝试获取TaskScheduler,然后是ScheduledExecutorService,然后它继续"回退到默认调度程序":

    if (this.registrar.hasTasks() && this.registrar.getScheduler() == null) {
        Assert.state(this.beanFactory != null, "BeanFactory must be set to find scheduler by type");
        try {
            // Search for TaskScheduler bean...
            this.registrar.setScheduler(this.beanFactory.getBean(TaskScheduler.class));
        }
        catch (NoUniqueBeanDefinitionException ex) {
            throw new IllegalStateException("More than one TaskScheduler exists within the context. " +
                    "Remove all but one of the beans; or implement the SchedulingConfigurer interface and call " +
                    "ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback.", ex);
        }
        catch (NoSuchBeanDefinitionException ex) {
            logger.debug("Could not find default TaskScheduler bean", ex);
            // Search for ScheduledExecutorService bean next...
            try {
                this.registrar.setScheduler(this.beanFactory.getBean(ScheduledExecutorService.class));
            }
            catch (NoUniqueBeanDefinitionException ex2) {
                throw new IllegalStateException("More than one ScheduledExecutorService exists within the context. " +
                        "Remove all but one of the beans; or implement the SchedulingConfigurer interface and call " +
                        "ScheduledTaskRegistrar#setScheduler explicitly within the configureTasks() callback.", ex);
            }
            catch (NoSuchBeanDefinitionException ex2) {
                logger.debug("Could not find default ScheduledExecutorService bean", ex);
                // Giving up -> falling back to default scheduler within the registrar...
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

您可以通过在org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor上设置至少一个INFO严重性来删除异常,如

<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
Run Code Online (Sandbox Code Playgroud)

使用logback时.

cron表达式有六个字段:

second (0-59), minute (0-59), hour (0-23, 0 = midnight), day (1-31), month (1-12), weekday (1-7, 1 = Sunday)
Run Code Online (Sandbox Code Playgroud)

语法可以在quartz文档中找到.我不确定"?" 因为,虽然页面说

'?' 允许使用字符表示日期和星期几字段.它用于指定"无特定值".当您需要在两个字段之一中指定某些内容而不是另一个字段时,这非常有用.

该页面上的示例实际使用?即使其他领域是*.恕我直言所有应该只使用*,所以为了每个午夜执行,表达式应该是

0 0 0 * * *
Run Code Online (Sandbox Code Playgroud)


ABH*_*HRI 5

为了解决这个问题,只需在config中创建Task Scheduler bean。

@Bean
    public TaskScheduler taskScheduler() {
        return new ConcurrentTaskScheduler();
    }
Run Code Online (Sandbox Code Playgroud)


Wim*_*uwe 5

使用 Spring Boot 2.0.5,我不断得到:

2018-11-20 11:35:48.046  INFO 64418 --- [  restartedMain] s.a.ScheduledAnnotationBeanPostProcessor : 
No TaskScheduler/ScheduledExecutorService bean found for scheduled processing
Run Code Online (Sandbox Code Playgroud)

摆脱它的唯一方法似乎是SchedulingConfigurer在类中使用接口,@Configuration如下所示:

@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
    private final int POOL_SIZE = 10;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();

        threadPoolTaskScheduler.setPoolSize(POOL_SIZE);
        threadPoolTaskScheduler.setThreadNamePrefix("my-scheduled-task-pool-");
        threadPoolTaskScheduler.initialize();

        scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:这取自https://www.callicoder.com/spring-boot-task-scheduling-with-scheduled-annotation/

  • 值得一提的是:这是一个 INFO 语句,而不是一个错误。该声明只是说它找不到任何自定义调度程序配置(这很好)。 (2认同)