石英作业配置中的无法解决的循环参考

发布于 2025-02-08 04:41:02 字数 2954 浏览 3 评论 0原文

我正在尝试用石英迁移旧的春季项目到最新的春季启动:

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzConfiguration implements InitializingBean {

  public static final Logger LOGGER = LoggerFactory.getLogger(QuartzConfiguration.class);
  public static final String JOB_KEY = "FinalizationJob";
  public static final String KEY = JOB_KEY + "_Trigger";

  private ApplicationContext context;

  @Autowired
  public QuartzConfiguration(ApplicationContext context) {
    this.context = context;
  }

  @Bean(name = "finalJobDetail")
  public JobDetail batchExpireUpdateJobDetail() {
    return JobBuilder.newJob(BatchExpireUpdateJob.class)
        .withIdentity(JobKey.jobKey(JOB_KEY))
        .storeDurably()
        .build();
  }

  @Override
  public void afterPropertiesSet() {
    Trigger newTrigger = newTrigger()
        .forJob(JOB_KEY)
        .withIdentity(triggerKey(KEY))
        .withSchedule(repeatSecondlyForever(100))
        .build();

    try {
      Scheduler obj = getSchedulerInstanceFromApplicationContext();
      if (obj.checkExists(triggerKey(KEY))) {
        obj.rescheduleJob(triggerKey(KEY), newTrigger);
      } else {
        obj.scheduleJob(newTrigger);
      }
    } catch (SchedulerException | NullPointerException e) {
      LOGGER.error("error {}", JOB_KEY, e);
    }
  }

  private Scheduler getSchedulerInstanceFromApplicationContext() {
    Scheduler obj = null;
    String [] beans = context.getBeanDefinitionNames();
    for (String bean: beans) {
      if (context.getBean(bean) instanceof Scheduler) {
        obj = (Scheduler) context.getBean(bean);
        break;
      }
    }
    return obj;
  }

  @DisallowConcurrentExecution
  private static class BatchExpireUpdateJob implements Job {

    private DatabaseService databaseService;

    @Autowired
    public BatchExpireUpdateJob(DatabaseService databaseService) {
      this.databaseService = databaseService;
    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
      try {
        LOGGER.info("Updating status");
        databaseService.updateStatus();
      } catch (Exception e) {
        LOGGER.error("Error ", e);
        throw new JobExecutionException(e);
      }
    }
  }
}

当我运行代码时,我得到的:

应用程序上下文中某些bean的依赖项形成一个周期:

Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'quartzConfiguration': Requested bean is currently in creation: Is there an unresolvable circular reference?

┌──->──┐
|  QuartzConfiguration defined in file C:\......\QuartzConfiguration.class]
└──<-──┘

I'm trying to migrate old Spring project with Quartz to the latest Spring Boot:

import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzConfiguration implements InitializingBean {

  public static final Logger LOGGER = LoggerFactory.getLogger(QuartzConfiguration.class);
  public static final String JOB_KEY = "FinalizationJob";
  public static final String KEY = JOB_KEY + "_Trigger";

  private ApplicationContext context;

  @Autowired
  public QuartzConfiguration(ApplicationContext context) {
    this.context = context;
  }

  @Bean(name = "finalJobDetail")
  public JobDetail batchExpireUpdateJobDetail() {
    return JobBuilder.newJob(BatchExpireUpdateJob.class)
        .withIdentity(JobKey.jobKey(JOB_KEY))
        .storeDurably()
        .build();
  }

  @Override
  public void afterPropertiesSet() {
    Trigger newTrigger = newTrigger()
        .forJob(JOB_KEY)
        .withIdentity(triggerKey(KEY))
        .withSchedule(repeatSecondlyForever(100))
        .build();

    try {
      Scheduler obj = getSchedulerInstanceFromApplicationContext();
      if (obj.checkExists(triggerKey(KEY))) {
        obj.rescheduleJob(triggerKey(KEY), newTrigger);
      } else {
        obj.scheduleJob(newTrigger);
      }
    } catch (SchedulerException | NullPointerException e) {
      LOGGER.error("error {}", JOB_KEY, e);
    }
  }

  private Scheduler getSchedulerInstanceFromApplicationContext() {
    Scheduler obj = null;
    String [] beans = context.getBeanDefinitionNames();
    for (String bean: beans) {
      if (context.getBean(bean) instanceof Scheduler) {
        obj = (Scheduler) context.getBean(bean);
        break;
      }
    }
    return obj;
  }

  @DisallowConcurrentExecution
  private static class BatchExpireUpdateJob implements Job {

    private DatabaseService databaseService;

    @Autowired
    public BatchExpireUpdateJob(DatabaseService databaseService) {
      this.databaseService = databaseService;
    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
      try {
        LOGGER.info("Updating status");
        databaseService.updateStatus();
      } catch (Exception e) {
        LOGGER.error("Error ", e);
        throw new JobExecutionException(e);
      }
    }
  }
}

When I run the code I get:

The dependencies of some of the beans in the application context form a cycle:

Invocation of init method failed; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'quartzConfiguration': Requested bean is currently in creation: Is there an unresolvable circular reference?

┌──->──┐
|  QuartzConfiguration defined in file C:\......\QuartzConfiguration.class]
└──<-──┘

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

把时间冻结 2025-02-15 04:41:02

看来您已升级到Spring Boot 2.6 so “默认情况下禁止参考” ,这是您获得beancurrantyIncreationException您可以去看的原因这里默认情况下禁止的循环因此,此处的问题是因为在注释@configuration QuartzConfiguration时首先创建了Bean。因此,当您致电以获取所有bean name context.getBeanDefinitionNames()这里时,您应该在这里找到QuartConfiguration bean名称,该名称是contect> context contection.getBean.getBean(bean) )这使得相同QUARTCONFIGURATION bean 循环参考 beancurrantyIncreationException被抛出,因此您有两个选择来解决此问题:

第一个选项

您可以直接调用调整器bean。您无需循环。

private Scheduler getSchedulerInstanceFromApplicationContext() {
    return context.getBean(Scheduler.class);
}

第二个选项

允许通过在application.propertiesapplication.yml中设置属性来允许循环引用。

spring.main.main.allow-circular-references = true

Looks like you upgraded to Spring Boot 2.6 so "Circular references are prohibited by default" that is the reason you get BeanCurrentlyInCreationException you can take a look here circular prohibited by default so the issue here is because first when having annotated @Configuration for QuartzConfiguration a bean is created for. So when you call to get all bean names context.getBeanDefinitionNames() here you should find the QuartConfiguration bean name which is being a referenced by context.getBean(bean) this makes a circular reference for the same QuartConfiguration bean then the BeanCurrentlyInCreationException is thrown, so you have two options to solve this:

First option

You might call the Scheduler bean directly. You don't have the need to loop.

private Scheduler getSchedulerInstanceFromApplicationContext() {
    return context.getBean(Scheduler.class);
}

Second option

Allow circular references by setting a property in application.properties or application.yml which the property is:

spring.main.allow-circular-references=true

纸伞微斜 2025-02-15 04:41:02

无论您是否初始化,您都可以将所有豆类名称

String [] beans = context.getBeanDefinitionNames();

。您可以自动调整器。

You are getting all beans name no matter if they are initialized or not

String [] beans = context.getBeanDefinitionNames();

You could autowire Scheduler.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文