当前位置: 首页 > 知识库问答 >
问题:

创建名称为“batchDataSource”的 Bean 时出错:请求的 Bean 当前正在创建中:是否存在无法解析的循环引用?

浦琪
2023-03-14

我有一个批处理配置。我看到批处理过程默认使用InMemoryMap。相反,我需要使用MySQL按批处理发送所有执行细节。但是当我使用以下代码时,我收到以下错误,

创建名称为“batchDataSource”的 Bean 时出错:请求的 Bean 当前正在创建中:是否存在无法解析的循环引用?

@Configuration
@EnableBatchProcessing
public class BatchProcess extends DefaultBatchConfigurer {

    private @Autowired Environment env;

    @Bean
    @StepScope
    public ItemReader reader() {
        ...
    }

    @Bean
    @StepScope
    public ItemProcessor processor() {
        ...
    }

    @Bean
    @StepScope
    public ItemWriter writer() {
        ...
    }

    @Bean
    @Primary
    public DataSource batchDataSource() {
        HikariDataSource hikari = new HikariDataSource();
        hikari.setDriverClassName(env.getProperty("spring.datasource.driver-class-name"));
        hikari.setJdbcUrl(env.getProperty("spring.datasource.url"));
        hikari.setUsername(env.getProperty("spring.datasource.username"));
        hikari.setPassword(env.getProperty("spring.datasource.password"));
        return hikari;
    }

    public JobRepository getJobRepository() {
        JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
        factory.setDataSource(batchDataSource());
        factory.setTransactionManager(manager());
        factory.afterPropertiesSet();
        return factory.getObject();
    }

    public PlatformTransactionManager manager() {
        return new ResourcelessTransactionManager();
    }

    @Bean
    public Step step() {
        return stepBuilderFactory.get("step")
                .chunk(1000)
                .reader(reader())
                .processor(processor())
                .writer(writer())
                .build();
    }

    @Bean
    public Job job() {
        return jobBuilderFactory.get("job")
                .flow(step())
                .end()
                .build();
    }

    @Bean
    public JobLauncher getJobLauncher() {
        SimpleJobLauncher launcher = new SimpleJobLauncher();
        launcher.setJobRepository(createJobRepository());
        return launcher;
    }
}

在我正在使用属性文件中,

spring.batch.job.enabled=false
spring.batch.initialize-schema=always

我错过了什么?我正在使用JPA。甚至为什么它不使用可用的JPA数据源?如何在MemoryMap中强制Spring批处理使用默认MySQL代替?

共有2个答案

仲孙思源
2023-03-14

首先,在pom中明确定义mysql连接器依赖项。xml并从项目中删除与内存映射相关的任何内容。

  <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
   </dependency>

如果您想手动使用bean定义自己的配置,则无法使用AutoConfiguration类,因为它们会在启动时自动为您创建所需的bean,如果您定义自己的自定义DB配置类,这可能会导致问题。因此,您必须排除DataSourceAutoConfigurationHibernateJpaAutoConfigurationDataSourceTransactionManagerAutoConfiguration来解决问题。

只需更新<code>@SpringBootApplication

@SpringBootApplication(
      exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
        DataSourceTransactionManagerAutoConfiguration.class
      }
    )
    public class App {
    
      public static void main(String[] args) {
        SpringApplication.run(App.class, args);
      }
    }
张心水
2023-03-14

您收到的错误消息可能不是最清楚的,但它应该为您指出正确的方向。您的代码中似乎有一个循环依赖项。

当您有两个(或更多)相互依赖的beansss时,就会发生这种情况,从而防止在没有另一个bean存在的情况下创建另一个bean(反之亦然),这就是众所周知的鸡和蛋的问题。通常可以通过setter注入和某种构造后初始化来避免这种情况。

我认为您已经通过扩展<code>DefaultBatchConfigurer

这完全没有必要,因为< code > DefaultBatchConfigurer 已经按照正确的顺序为您创建了< code>JobRepository 、< code>JobExplorer和< code>JobLauncher。

从DefaultBatchConfigurer:

@PostConstruct
    public void initialize() {
        try {
            this.jobRepository = createJobRepository();
            this.jobExplorer = createJobExplorer();
            this.jobLauncher = createJobLauncher();
        } catch (Exception e) {
            throw new BatchConfigurationException(e);
        }
    }

如果您要扩展DefaultBatchConfigrer,那么我建议您从代码中删除以下方法:

    < Li > < code > getJobRepository() < li> manager() < Li > < code > getjob launcher()

从代码示例中可以看出,您似乎已经在设置以下属性(在应用程序.properties 文件中?):

spring.datasource.jdbcUrl=...
spring.datasource.username=...
spring.datasource.password=...
spring.datasource.driverClassName=...

这应该足以允许Spring的自动配置为您自动创建Hikari<code>数据源数据源,这将通过setDataSource()自动连接到DefaultBatchConfigurer

但是,在您的代码示例中,您还定义了一个名为batchDataSource()@Bean注释方法,它看起来与您应该从Spring AutoConfiguration接收的内容没有什么不同。只要您配置了前面提到的spring.datasource属性,您也应该能够消除batchDataSource(),但我认为这没有必要,所以您的选择。

如果您仍然想要手动配置您的< code>DataSource,那么我建议您不要扩展< code > DefaultBatchConfigurer ,而是在一个配置类中为它定义一个自定义bean,在那里您可以直接传入您的自定义< code>DataSource(基于我目前对您的用例的了解)。

@Bean
public BatchConfigurer batchConfigurer(){
    return new DefaultBatchConfigurer( batchDataSource() );
}
 类似资料: