1

在升级调度程序未按预期工作后,我已将我的 spring-boot 应用程序从 1.x 更新到 2.x。得到以下异常。

org.quartz.SchedulerException: Job instantiation failed
        at org.springframework.scheduling.quartz.AdaptableJobFactory.newJob(AdaptableJobFactory.java:47)
        at org.quartz.core.JobRunShell.initialize(JobRunShell.java:127)
        at org.quartz.core.QuartzSchedulerThread.run(QuartzSchedulerThread.java:392) Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.schedulers.simplejobs.SimpleJobExecutions': Unsatisfied dependency expressed through field 'sampleService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.service.SampleService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:351)
        at org.springframework.scheduling.quartz.SpringBeanJobFactory.createJobInstance(SpringBeanJobFactory.java:90)
        at com.scheduler.factory.JobFactory.createJobInstance(JobFactory.java:35)
        at org.springframework.scheduling.quartz.AdaptableJobFactory.newJob(AdaptableJobFactory.java:43)
        ... 2 common frames omitted Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.service.SampleService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1655)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1214)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1168)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
        ... 11 common frames omitted

我已经尝试了许多来自 SO 的参考资料,但建议的配置没有帮助。

以下是堆栈详细信息。

春季启动 2.1.5

春天 5.1.7

石英 2.3.1

这是我的代码库。


public final class JobFactory  extends SpringBeanJobFactory {

    private transient AutowireCapableBeanFactory beanFactory;

    private static final Logger LOGGER = LoggerFactory.getLogger(JobFactory.class);

    public void setApplicationContext(final ApplicationContext context) {
        Stream.of(context.getBeanDefinitionNames())
            .filter(s -> s.startsWith("sample"))
            .forEach(beanName -> LOGGER.debug("applicationContext beans {}",beanName));
        beanFactory = context.getAutowireCapableBeanFactory();
    }

    @Override
    protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
        final Object job = super.createJobInstance(bundle);
        LOGGER.debug("createJobInstance job {}",job);
        beanFactory.autowireBean(job);
        LOGGER.debug("createJobInstance autowireBean job {}",job);
        return job;
    }
@Component
public class SimpleJobExecutions extends QuartzJobBean {


    @Autowired
    public SampleService sampleService;

    @Override
    public void executeInternal(JobExecutionContext context)  throws JobExecutionException {
        try {
            SampleDTO sample = new SampleDTO();
            sample.setName("Name");
            sample.setAge(25);
            SampleDTO sampleObj = sampleService.save(sample);
        } catch (Exception ex) {
            throw new JobExecutionException(ex);
        }
    }
@Service("sampleService")
public class SampleServiceImpl implements SampleService {

    @Autowired
    SampleRepository sampleRepository;

    @Autowired
    SampleMapper sampleMapper;

   @Override
   public SampleDTO save(SampleDTO sampleDTO) {
      log.info("Request to save Sample : {}", sampleDTO);
      Sample sample = sampleMapper.toEntity(sampleDTO);
      sample = sampleRepository.save(sample);
      return sampleMapper.toDto(sample);
  }

}

我可以从应用程序上下文中打印所有 bean,但它不会在作业执行时注入。

4

3 回答 3

1

最后,我找到了这个问题的根本原因。

删除以下依赖项后,自动装配其他 bean 引用开始工作。

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <version>2.1.5.RELEASE</version>
  </dependency>

开发工具依赖项正在与应用程序依赖项产生冲突,并且它不允许仅在 QuartzJobBean 执行中创建 bean 引用。

于 2019-09-25T05:53:00.023 回答
0

你好我会试着回答这个问题

默认情况下,您的SchedulerFactoryBean使用 AdaptableJobFactory( https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/quartz/SchedulerFactoryBean.html#setJobFactory-org.quartz.spi.JobFactory ) 它没有自动装配功能,因此您需要在此处指定 Spring 的 SpringBeanJobFactory 实例,基本上您需要将其指定给调度程序。前任:

@Autowired
private ApplicationContext applicationContext;

@Bean
public SchedulerFactoryBean schedulerFactoryBean() {
    SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
    JobFactory jobFactory = new JobFactory();
    jobFactory.setApplicationContext(applicationContext);
    schedulerFactoryBean.setJobFactory(jobFactory);
    return schedulerFactoryBean;
}

替代方法:

如果上面的代码不起作用,那么您可以简单地尝试从您的 executeInternal() 方法中的应用程序上下文中获取 bean

 @Component
public class SimpleJobExecutions extends QuartzJobBean {

    @Override
    public void executeInternal(JobExecutionContext context)  throws JobExecutionException {
        try {
            ApplicationContext applicationContext = (ApplicationContext)
                        context.getScheduler().getContext().get("applicationContext");
            SampleService sampleService = (SampleService) applicationContext.getBean(SampleService.class);
            SampleDTO sample = new SampleDTO();
            sample.setName("Name");
            sample.setAge(25);
            SampleDTO sampleObj = sampleService.save(sample);
        } catch (Exception ex) {
            throw new JobExecutionException(ex);
        }
    }
于 2019-09-23T13:01:08.273 回答
-1

首先,关于类中的行@Autowired public SampleServiceImpl sampleService;SimpleJobExecutions对接口进行编码将是一个好习惯。

我觉得容器中有一个代理bean,它实现了SimpleService,因为你试图注入SimpleServiceImpl它没有被注入。(注意代理对象不是'SimpleServiceImp')。

要测试这是否是您的情况,只需尝试SimpleServiceImpl通过接口注入。

只需更换:

@Autowired public SampleServiceImpl sampleService;

@Autowired public SampleService sampleService;

希望能帮助到你。

更新:(只是做一些澄清)

当您的 bean 被代理包装时,代理对象实现您的 bean 的接口,并且由于在您的问题的先前版本(编辑之前)中您按类(而不是接口)注入 bean,因此没有此类的 bean (但有一个接口类型),因此容器无法找到这样的 bean 并抛出:

org.springframework.beans.factory.NoSuchBeanDefinitionException:  No qualifying bean of type 'com.service.SampleService' available
于 2019-09-22T14:31:02.303 回答