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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30431776/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 09:38:15  来源:igfitidea点击:

Using @Scheduled and @EnableScheduling but gives NoSuchBeanDefinitionException

javacronscheduled-tasksspring-4

提问by logixplayer

I have followed very simple examplesonline to set up a cron job in Spring yet I keep getting this error in my Tomcat startup log each and every time:

我已经按照非常简单的在线示例在 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

And the 2 java classes used to implement the cron:

以及用于实现 cron 的 2 个 java 类:

1) The @Configuration class:

1)@Configuration类:

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

and Cron job class:

和 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");
    }
}

As a side note, the cron job runs at midnight but it also seems to run randomly at other times. Not sure if this is a bug or my cron expression is wrong: @Scheduled(cron = "0 0 * * * *")

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

My main concern at this time is why am I getting ScheduledAnnotationBeanPostProcessorerrors? It's looking for a TaskScheduler and ScheduledExectorService.I just need to fire this once a day. I am not doing any concurrent processing or where I need multiple threads. Ultimately are these errors harmful OR do I need to fix them?

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

回答by xtian

EDIT: the best answer is hereand it involves creating an Executor:

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

@Configuration
@EnableAsync
public class AppContext extends WebMvcConfigurationSupport {
    @Bean
    public Executor taskExecutor() {
        return new SimpleAsyncTaskExecutor();
    }
}

PREVIOUS (still valid though):

以前(尽管仍然有效):

The NoSuchBeanDefinitionException is logged with a DEBUG severity and can be safely ignored. If you look at the source code for ScheduledAnnotationBeanPostProcessor, you see that it first tries to get a TaskScheduler, then a ScheduledExecutorService, then it keeps going on "falling back to default scheduler":

NoSuchBeanDefinitionException 与 DEBUG 严重性一起记录,可以安全地忽略。如果您查看 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...
            }
        }
    }

You can remove the exception by setting at least a INFO severity on org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor, like

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

<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>

when using logback.

使用 logback 时。

The cron expression has six fields:

cron 表达式有六个字段:

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

The syntax can be found in the quartz docs. I'm not sure about the "?" character because, although the page says

语法可以在石英文档中找到。我不确定“?” 字符因为,虽然页面上说

The '?' character is allowed for the day-of-month and day-of-week fields. It is used to specify “no specific value”. This is useful when you need to specify something in one of the two fields, but not the other.

这 '?' 月份和星期几字段允许使用字符。它用于指定“无特定值”。当您需要在两个字段之一而不是另一个字段中指定某些内容时,这很有用。

the examples on that page actually use ? even when the other field is *. IMHO all should work with just *, so in order to execute every midnight, the expression should be

该页面上的示例实际使用?即使另一个字段是 *. 恕我直言,所有人都应该只使用 *,所以为了在每个午夜执行,表达式应该是

0 0 0 * * *

回答by Eduardo G

I agree you can ignore it but just changing the severity will not fix it. I had the same issue but I am using xml instead of annotations, and in my case it happened because I did not included the executor on my bean definition. So adding this fixed it:

我同意你可以忽略它,但仅仅改变严重性并不能解决它。我遇到了同样的问题,但我使用的是 xml 而不是注释,在我的情况下,这是因为我没有在 bean 定义中包含执行程序。所以添加这个修复它:

<task:annotation-driven executor="myExecutor"
    scheduler="myScheduler" />
<task:executor id="myExecutor" pool-size="5" />
<task:scheduler id="myScheduler" pool-size="10" />

I hope it helps.

我希望它有帮助。

Regards.

问候。

回答by randy

according to exception Info "Could not find default TaskScheduler bean", the config should define "TaskScheduler" rather than "Executor"

根据异常信息“找不到默认的 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();
   }

}

}

回答by ABHAY JOHRI

For solving this problem just create task scheduler bean in config.

为了解决这个问题,只需在配置中创建任务调度程序 bean。

@Bean
    public TaskScheduler taskScheduler() {
        return new ConcurrentTaskScheduler();
    }

回答by Wim Deblauwe

With Spring Boot 2.0.5, I keep getting:

使用 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

The only way to get rid of it seems to be using SchedulingConfigurerinterface in your @Configurationclass like this:

摆脱它的唯一方法似乎是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);
    }
}

Note: This was taken from https://www.callicoder.com/spring-boot-task-scheduling-with-scheduled-annotation/

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