SpringBatch異常To use the default BatchConfigurer the context must contain no more thanone DataSource

SpringBoot整合SpringBatch項目,已將代碼開源至github,訪問地址:https://github.com/cmlbeliever/SpringBatch 歡迎star or fork!css

在框架整合的過程當中,因爲須要添加db讀寫分離配置,所以項目中有兩個DataSource,運行batch後報錯以下:java

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:779)
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:760)
    at org.springframework.boot.SpringApplication.afterRefresh(SpringApplication.java:747)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
    at com.cml.learning.framework.module.BaseModule.run(BaseModule.java:39)
    at com.cml.learning.module.bat00X.Bat00XModule.main(Bat00XModule.java:20)
Caused by: java.lang.IllegalStateException: To use the default BatchConfigurer the context must contain no more thanone DataSource, found 2
    at org.springframework.batch.core.configuration.annotation.AbstractBatchConfiguration.getConfigurer(AbstractBatchConfiguration.java:108)
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration.initialize(SimpleBatchConfiguration.java:114)
    at org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration$ReferenceTargetSource.createObject(SimpleBatchConfiguration.java:142)
    at org.springframework.aop.target.AbstractLazyCreationTargetSource.getTarget(AbstractLazyCreationTargetSource.java:86)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:192)
    at com.sun.proxy.$Proxy55.getJobInstances(Unknown Source)
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.getNextJobParameters(JobLauncherCommandLineRunner.java:131)
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute(JobLauncherCommandLineRunner.java:212)
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs(JobLauncherCommandLineRunner.java:231)
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties(JobLauncherCommandLineRunner.java:123)
    at org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run(JobLauncherCommandLineRunner.java:117)
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:776)
    ... 5 common frames omitted

意思是要使用default BatchConfigurer,則項目中只能有一個Datasource。git

根據異常堆棧信息,找到拋出此異常的源碼位置和實現代碼:
org.springframework.batch.core.configuration.annotation.AbstractBatchConfigurationgithub

@Autowired(required = false)
private Collection<DataSource> dataSources;

protected BatchConfigurer getConfigurer(Collection<BatchConfigurer> configurers) throws Exception {
        if (this.configurer != null) {
            return this.configurer;
        }
        if (configurers == null || configurers.isEmpty()) {
            if (dataSources == null || dataSources.isEmpty()) {
                DefaultBatchConfigurer configurer = new DefaultBatchConfigurer();
                configurer.initialize();
                this.configurer = configurer;
                return configurer;
            } else if(dataSources != null && dataSources.size() == 1) {
                DataSource dataSource = dataSources.iterator().next();
                DefaultBatchConfigurer configurer = new DefaultBatchConfigurer(dataSource);
                configurer.initialize();
                this.configurer = configurer;
                return configurer;
            } else {
                throw new IllegalStateException("To use the default BatchConfigurer the context must contain no more than" +
                                                        "one DataSource, found " + dataSources.size());
            }
        }
        if (configurers.size() > 1) {
            throw new IllegalStateException(
                    "To use a custom BatchConfigurer the context must contain precisely one, found "
                            + configurers.size());
        }
        this.configurer = configurers.iterator().next();
        return this.configurer;
    }

根據源碼得知,當數據源不存的時候,BatchConfigure會將batch數據存儲到內存中,當數據源只有一個時,會根據數據源創建batch執行所須要的表。當數據源有多個的時候就拋出異常,這樣難怪,由於BatchConfigure在多個數據源的時候,它根本不知道要根據哪一個數據源創建batch執行所須要的表。
既然知道了緣由,只須要自定義BatchConfigure,而且在多數據源的狀況下指定一個默認的數據源便可解決。spring

實現步驟:
一、將框架SimpleBatchConfiguration,AbstractBatchConfiguration源碼複製出來
二、重寫AbstractBatchConfiguration.getConfigurer方法,設置默認數據源markdown

protected BatchConfigurer getConfigurer(Collection<BatchConfigurer> configurers) throws Exception {
        if (this.configurer != null) {
            return this.configurer;
        }
        if (configurers == null || configurers.isEmpty()) {
            if (defaultDataSource == null) {
                throw new IllegalStateException("Data source can not be null!!!");
            }

            DefaultBatchConfigurer configurer = new DefaultBatchConfigurer(defaultDataSource);
            configurer.initialize();
            this.configurer = configurer;
            return configurer;
        }
        if (configurers.size() > 1) {
            throw new IllegalStateException("To use a custom BatchConfigurer the context must contain precisely one, found " + configurers.size());
        }
        this.configurer = configurers.iterator().next();
        return this.configurer;
    }

三、添加註解,將重寫的BatchConfigure引入框架

@Import({ SimpleBatchConfiguration.class })

四、通過以上三個步驟,便可實現多數據源下SpringBatch啓動報錯問題ui

以上代碼已經整合到SpringBatch,已將代碼開源至github,訪問地址:https://github.com/cmlbeliever/SpringBatch 歡迎star or fork!this

若是有其餘更好的方法,還請不吝賜教。spa

相關文章
相關標籤/搜索