NoSuchBeanDefinitionException:没有要自动装配的 JobLauncher 类型的合格 bean

NoSuchBeanDefinitionException: No qualifying bean of type JobLauncher to autowire

我正在关注 this spring batch tutorial。现在,我想 运行 完成 API 的工作,所以我将它作为一个 Web 项目并在控制器之后实现,但是 beans 没有自动装配。

examples.spring.batch.web.controller.JobLauncherController

@Controller
@RequestMapping("/run")
public class JobLauncherController {

  @Autowired
  private JobLauncher jobLauncher;

  @Autowired
  private Job job;

  @RequestMapping(method = RequestMethod.GET, value = "/runJob")
  @ResponseBody
  public void launchImportDataJob() throws Exception {
    jobLauncher.run(importDataJob, new JobParameters());
  }
}

/WEB-INF/spring/batch/applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
  xmlns:task="http://www.springframework.org/schema/task" xmlns:cache="http://www.springframework.org/schema/cache"
  xmlns:p="http://www.springframework.org/schema/p" xmlns:mvc="http://www.springframework.org/schema/mvc"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.2.xsd
        http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-4.2.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

  <!-- enable auto-scan for all @Repository, @Service, @Controller java files 
    for beans -->
  <context:component-scan base-package="examples.spring">
  </context:component-scan>

  <!-- Import extra configuration -->
  <import resource="/WEB-INF/spring/batch/database.xml"/>
  <import resource="/WEB-INF/spring/batch/spring-batch.xml"/>
  <import resource="/WEB-INF/spring/batch/job.xml"/>

</beans>

/WEB-INF/spring/batch/database.xml

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="
  http://www.springframework.org/schema/beans 
  http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

    <!-- stored job-metadata in database -->
  <bean id="jobRepository"
  class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="transactionManager" ref="transactionManager" />
  <property name="databaseType" value="mysql" />
  </bean>

    <bean id="transactionManager"
  class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />


    <bean id="jobLauncher"
  class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
  <property name="jobRepository" ref="jobRepository" />
    </bean>

</beans>

堆栈跟踪

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jobLauncherController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.batch.core.launch.JobLauncher examples.spring.batch.web.controller.JobLauncherController.jobLauncher; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.batch.core.launch.JobLauncher] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=jobLauncher)}
  at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
  at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
  at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:305)
  at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
  at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
  at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
  at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:835)
  at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
  at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:667)
  at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:633)
  at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:681)
  at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:552)
  at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:493)
  at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
  at javax.servlet.GenericServlet.init(GenericServlet.java:158)
  at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1231)
  at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1144)
  at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1031)
  at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4914)
  at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5201)
  at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
  at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
  at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1399)
  at java.util.concurrent.FutureTask.run(FutureTask.java:266)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.batch.core.launch.JobLauncher examples.spring.batch.web.controller.JobLauncherController.jobLauncher; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.batch.core.launch.JobLauncher] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=jobLauncher)}
  at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:571)
  at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
  at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
  ... 29 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.springframework.batch.core.launch.JobLauncher] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=jobLauncher)}
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1373)
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1119)
  at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
  at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:543)
  ... 31 more

web.xml

<web-app>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/applicationContext.xml</param-value>
  </context-param>
  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring/spring-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

在加载 applicationContext.xml

的 web.xml 上使用 Spring 侦听器
<listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

在我的应用程序 class 中使用以下内容,而不必弄乱 web.xml(我的项目中甚至没有):

@EnableAutoConfiguration
@Configuration
@ImportResource({"classpath*:applicationContext.xml"})

另见 Spring-boot automatically import applicationContext.xml?

或者使用更简洁的版本

@SpringBootApplication
@ImportResource("applicationContext.xml")

Loading applicationcontext.xml when using SpringApplication