最近使用 Spring + SpringMvc + Quartz 的系统中,使用 @annotation 注解方式, 直接在类的方法上使用 @Scheduled(cron=”0 /5 * * ?”)来实现定时任务,在使用 debug 日志级别时,启动提示 Could not find default TaskScheduler bean 异常:
10:44:18.816 [main] DEBUG org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor - Could not find default TaskScheduler bean org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.scheduling.TaskScheduler' available at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:996) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:994) at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.resolveSchedulerBean(ScheduledAnnotationBeanPostProcessor.java:285) at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:226) at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:203) at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:97) at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:393) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:347) at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:883) at org.springframework.context.support.AbstractApplicationContext.__refresh(AbstractApplicationContext.java:546) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:41010) at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668) at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634) at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682) at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553) at org.springframework.web.servlet.FrameworkServlet.jrInitWebApplicationContext(FrameworkServlet.java:40002) at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494) at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:171) at javax.servlet.GenericServlet.init(GenericServlet.java:158) at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1123) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1078) at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:971) at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4849) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5165) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1382) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1372) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:907) at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1382) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1372) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:907) at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.StandardService.startInternal(StandardService.java:423) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:933) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.startup.Catalina.start(Catalina.java:637) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492)
10:44:18.823 [main] DEBUG org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor - Could not find default ScheduledExecutorService bean org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'java.util.concurrent.ScheduledExecutorService' available at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:996) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:994) at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.resolveSchedulerBean(ScheduledAnnotationBeanPostProcessor.java:285) at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:247) at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:203) at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:97) at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:393) at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:347) at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:883) at org.springframework.context.support.AbstractApplicationContext.__refresh(AbstractApplicationContext.java:546) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:41010) at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:668) at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:634) at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:682) at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:553) at org.springframework.web.servlet.FrameworkServlet.jrInitWebApplicationContext(FrameworkServlet.java:40002) at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:494) at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:171) at javax.servlet.GenericServlet.init(GenericServlet.java:158) at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1123) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1078) at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:971) at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4849) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5165) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1382) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1372) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:907) at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1382) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1372) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134) at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:907) at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:262) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.StandardService.startInternal(StandardService.java:423) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:933) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) at org.apache.catalina.startup.Catalina.start(Catalina.java:637) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492) 10:44:18.823 [main] INFO org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor - No TaskScheduler/ScheduledExecutorService bean found for scheduled processing
很困惑,配置都没有问题啊?通过在 stackoverflow 辛苦的寻找才发现其实是定时任务框架的一个机制,原来在 org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.inishRegistration():这个方法中,是这样处理的:
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.setTaskScheduler(this.beanFactory.getBean(TaskScheduler.class)); } 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 (NoSuchBeanDefinitionException ex2) { logger.debug("Could not find default ScheduledExecutorService bean", ex); // Giving up -> falling back to default scheduler within the registrar... } } }
上面代码中,程序通过 beanfactory.getbean 方法找到在 Spring 中注册的调度器, 如果 ScheduledExecutorService 没有找到,就使用默认的调度器。所以,这个过程中如果没有找到 ScheduledExecutorService,就会在 debug 级别的日志输出一个异常:
logger.debug("Could not find default TaskScheduler bean", ex);
当然,这个你所看到的异常并不影响应用程序运行,如果你不想看到这个异常,就可以通过提升 org.springframework.scheduling 这个包下日志级别来屏蔽这个不合理的异常:
logback & log4j xml:
<logger name="org.springframework.scheduling"> <level value="info" /> </logger>
log4j.properties
log4j.logger.org.springframework.scheduling=INFO
当然,你也可以通过配置上下文:
@Configuration @EnableAsync public class AppContext extends WebMvcConfigurationSupport{ @Bean public Executor taskExecutor() { return new SimpleAsyncTaskExecutor(); } }
或者配置 spring-mvc.xml 文件:
<task:executor id="executor" pool-size="100"/> <task:scheduler id="scheduler" pool-size="100"/> <task:annotation-driven scheduler="scheduler" executor="executor" proxy-target-class="true"/>
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于