Spring boot Batch 的启动原理- Configuration
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring boot Batch 的启动原理- Configuration相关的知识,希望对你有一定的参考价值。
参考技术A Spring boot 整合了web 和batch ,但是他们肯定不是同一条路, 在spring boot 中,会推断当前的运行环境。 this.webApplicationType = WebApplicationType.deduceFromClasspath();从上文可以看出,Spring 尝试从classpath 里找到特征类,来判断当前app 是什么类型。当然这种判断是有局限性的,有可能是transitive 带进来一个带有servlet 的类被当成了 WebApplicationType.SERVLET, 实际上是个WebApplicationType.NONE;。如果不想以web 运行就是想运行batch 可以在application.properties 强行指定WebApplicationType
具体发生作用的请看下面的stack trace
当一个batch application需要启动,需要 配置JobRepository, Datasource 等等,所有的开始都来自一个annotation @EnableBatchProcessing
当加入@EnableBatchProcessing 时, BatchConfigurationSelector 开始启动,怎么启动的大家可以参考下面的stack trace。
import 类主要是由ConfigurationClassPostProcessor 来实现的。 当BatchConfigurationSelector 被调用的时候,我们可以看到他有两条支路。
那么这两条路有啥不同呢。 主要是job 定义的方式不同。
modular = true 的情况下,下面是一个例子
可以有多个子ApplicationContextFactory ,这样好处是在除了job 大家不可以重复,因为是在不同的context 里,其他的step,reader, writer,processor,mapper ,以及所有的bean等等都可以重名。
那为什么Job 不可以重复,是因为虽然可以重复,但是如果job 也重复,对用户来讲太不友好了。用户可能不知道自己配的是哪个context 的job。具体为什么可以重名要看看GenericApplicationContextFactory 的实现。
当GenericApplicationContextFactory::createApplicationContext, 会触发 ApplicationContextHelper 的构造函数 从而调用 loadConfiguration(config) 把定义的bean 加入到context 里。那么有个问题,parent 在哪里设置,createApplicationContext 是什么时候调用的。
我们继续看ModularConfiguration
从Modular 的角度来看 首先他可以外部注入一个Configurer,如果没有就选择DefaultBatchConfigurer, 如果有多个选择则会抛出。
当然Datasource也可以选择外部注入,或者由 DefaultBatchConfigurer::initialize 方法 SimpleJobLauncher , JobRepository 和 JobExplorer 都是 由FactoryBean 的方式实现的。
在这个DefaultBatchConfigurer 中可以看到JobLauncher 的类型是
initialize 里MapJobRepositoryFactoryBean 这个可以重点读一下。 首先用FactoryBean的模式实现了一个ProxyBean,如果想了解FactoryBean 的用法,这是个典型的例子。但是这个FactoryBean 是以api 行为直接调用的,并没有注册到Spring 的context 中。
配置好job 需要的 jobRepository ,jobLauncher等 那么重点来了,下面的AutomaticJobRegistrar 就是来处理ApplicationContextFactory
这个逻辑是把所有的ApplicationContextFactory 的bean instance 放入到AutomaticJobRegistrar 里去。 这就回到了第一个问题,parent context 是什么时候放进去的。就是在
context.getBeansOfType(ApplicationContextFactory.class) 请看下面的调用栈,在ApplicationContextAwareProcessor 里会自动把parent context 注入。
但是放进去啥时候用呢?我们看一下AutomaticJobRegistrar
原来AutomaticJobRegistrar 是个Smartlifecycle, 从Smartlifecycle的细节可以从 Springboot Smartlifecycle 来得知。它就是在所有bean都初始化结束后开始进行的一个阶段。在这个start 方法中,开始遍历所有的ApplicationContextFactory, 来进行加载。 从上文这个jobLoader 是DefaultJobLoader。
那么可以看看DefaultJobLoader::doLoad 方法
这里有几个关键调用 第一个是createApplicationContext, 把context 里定义的全部加载到Spring context里去,这就满足了GenericApplicationContextFactory 工作的两个条件。第二个是doRegister(context, job) 里 jobRegistry.register(jobFactory);
我们看一下JobRepository的实现MapJobRegistry::register 方法,在这里就把jobname 和jobFactory 的键值对存储起来了。
这样就可以通过JobRepository 这个bean 拿到所有注册的job 了。
咱们再回来看@EnableBatchProcessing 这个annotation,当没有设定modular 的时候是比较简单的,只是实现了一个proxy based 的Job的bean。
同样也只有BatchConfigurer 来配置。 这个逻辑和Modular 是一样的。从这两个配置知道, Modular 注册了在子context的配置,并且加载。 但是当以正常bean 的方式存在的,是怎么读进来的呢。这时候就要看 JobRegistryBeanPostProcessor
这个 postProcessAfterInitialization 方法里, 对每个job 类型的bean, jobRegistry 加入了ReferenceJobFactory。 这样所有的以bean 的方式定义的都可以通过jobRegistry获得。
Spring Batch/Spring Boot 总是自动启动我的工作
【中文标题】Spring Batch/Spring Boot 总是自动启动我的工作【英文标题】:Spring Batch/Spring Boot always auto-start my jobs 【发布时间】:2016-11-04 08:00:11 【问题描述】:我正在使用 Spring Boot 1.3.3.RELEASE
和 Spring Batch 3.0.6.RELEASE
,并且无法让 Spring Batch/Spring Boot 不自动启动我的工作。
这个问题类似于how to stop spring batch scheduled jobs from running at first time when executing the code?
我有以下测试类:
@RunWith(SpringJUnit4ClassRunner.class)
@Configuration
@ComponentScan(useDefaultFilters = false,
includeFilters = @ComponentScan.Filter(value = GetMarkerViaSpringBatchApplicationTest.class,
type = FilterType.ASSIGNABLE_TYPE) )
@EnableBatchProcessing
//@IntegrationTest("spring.batch.job.enabled=false")
@EnableAutoConfiguration
@TestPropertySource(
locations = "classpath:env.properties", "classpath:application.properties", "classpath:database.properties",
properties = "spring.batch.job.enabled=false")
@SpringApplicationConfiguration(classes = GetMarkerViaSpringBatchApplicationTest.class,
locations = "classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml")
public class GetMarkerViaSpringBatchApplicationTest
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@Test
public void testLaunchJob() throws Exception
JobExecution jobExecution = jobLauncherTestUtils.launchJob();
assertThat(jobExecution.getStatus()).isEqualTo(BatchStatus.COMPLETED);
在与测试类相同的目录(包)中,我有配置文件GetMarkerViaSpringBatchApplicationTest-context.xml
。
GetMarkerViaSpringBatchApplicationTest-context.xml
内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:batch="http://www.springframework.org/schema/batch"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<import resource="classpath:/META-INF/spring/get-marker-job-new.xml" />
<bean id="jobLauncherTestUtils" class="org.springframework.batch.test.JobLauncherTestUtils" />
<bean id="batchConfigurer" class="org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer">
<constructor-arg name="dataSource" ref="hsqlDataSource" />
</bean>
</beans>
get-marker-job-new.xml
内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:batch="http://www.springframework.org/schema/batch" xmlns:task="http://www.springframework.org/schema/task"
xmlns:file="http://www.springframework.org/schema/integration/file" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<import resource="classpath:META-INF/spring/application-context.xml" />
<import resource="classpath:META-INF/spring/database.xml" />
<!-- The @EnableBatchProcessing on the main class sets up: job-repository, jobLauncher, and jobRepository -->
<!-- Spring Boot with Spring Batch doesn't like multiple DataSources since it doesn't know which one -->
<!-- to pick for Spring Batch. This class will therefore coerce to pick the proper HSQL dataSource. -->
<!-- See https://***.com/questions/25540502/use-of-multiple-datasources-in-spring-batch -->
<bean id="batchConfigurer" class="org.springframework.batch.core.configuration.annotation.DefaultBatchConfigurer">
<constructor-arg name="dataSource" ref="hsqlDataSource" />
</bean>
<bean id="foo" class="myClass" />
<bean id="myTasklet" class="org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter">
<property name="targetObject" ref="myClass" />
<property name="targetMethod" value="deliver" />
</bean>
<batch:job id="batchJob" restartable="false">
<batch:step id="step1">
<batch:tasklet ref="myTasklet"/>
</batch:step>
</batch:job>
</beans>
application-context.xml
内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
xmlns:oxm="http://www.springframework.org/schema/oxm" xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<import resource="classpath:META-INF/spring/database.xml" />
<!-- load properties from config files -->
<context:property-placeholder location="classpath:env.properties,classpath:application.properties,classpath:database.properties" />
<bean id="transactionManager" class="org.springframework.batch.support.transaction.ResourcelessTransactionManager" />
</beans>
database.xml
内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" 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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">
<bean id="myDataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<property name="driverClassName" value="$jdbc.myco.driverClassName" />
<property name="username" value="$jdbc.myco.username" />
<property name="password" value="$jdbc.myco.encpassword" />
<property name="jdbcUrl" value="$jdbc.myco.url" />
<property name="maximumPoolSize" value="$jdbc.myco.pool.maxactive" />
</bean>
<alias alias="dataSource" name="myDataSource" />
<bean id="hsqlDataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close" primary="true">
<property name="driverClassName" value="$jdbc.hsqldb.driverClassName" />
<property name="username" value="$jdbc.hsqldb.username" />
<property name="password" value="$jdbc.hsqldb.password" />
<property name="jdbcUrl" value="$jdbc.hsqldb.url" />
<property name="maximumPoolSize" value="$jdbc.hsqldb.pool.maxactive" />
</bean>
</beans>
application.properties
(在根目录中,也在类路径中):
spring.datasource.platform=sqlserver
spring.profiles.active=local
spring.batch.job.enabled=true
spring.batch.initializer.enabled=true
spring.batch.schema=classpath:org/springframework/batch/core/schema-hsqldb.sql
注意spring.batch.job.enabled=true
在application.properties
中,但在@IntegrationTest
和@TestPropertySource
中为假。
每当我在application.properties
中设置spring.batch.job.enabled=true
时,无论在@IntegrationTest
和@TestPropertySource
中尝试各种spring.batch.job.enabled=false
组合,每当我运行此测试时,工作就会在jobLauncherTestUtils.launchJob()
被调用之前开始。
运行日志:
15:52:49,083 (o.s.test.context.support.AbstractDirtiesContextTestExecutionListener) - Before test class: context [DefaultTestContext@1733f619 testClass = GetMarkerViaSpringBatchApplicationTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@5461ef35 testClass = GetMarkerViaSpringBatchApplicationTest, locations = 'classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml', classes = 'class xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest', contextInitializerClasses = '[]', activeProfiles = '', propertySourceLocations = 'classpath:env.properties, classpath:application.properties, classpath:database.properties', propertySourceProperties = 'spring.batch.job.enabled=false, marker=SELC_ALPHA_DONE, marker_date=2016/06/21, interval=1, times=1, is_fail=true, fail_path=$pkg.out\\failed_alpha_report', contextLoader = 'o.s.boot.test.SpringApplicationContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null].
15:52:49,099 (o.s.test.context.support.DependencyInjectionTestExecutionListener) - Performing dependency injection for test context [[DefaultTestContext@1733f619 testClass = GetMarkerViaSpringBatchApplicationTest, testInstance = xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest@6769360f, testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@5461ef35 testClass = GetMarkerViaSpringBatchApplicationTest, locations = 'classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml', classes = 'class xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest', contextInitializerClasses = '[]', activeProfiles = '', propertySourceLocations = 'classpath:env.properties, classpath:application.properties, classpath:database.properties', propertySourceProperties = 'spring.batch.job.enabled=false, marker=SELC_ALPHA_DONE, marker_date=2016/06/21, interval=1, times=1, is_fail=true, fail_path=$pkg.out\\failed_alpha_report', contextLoader = 'o.s.boot.test.SpringApplicationContextLoader', parent = [null]]]].
15:52:50,572 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:52:50,572 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:52:50,572 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'
15:52:50,665 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:52:50,665 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:52:50,665 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'
15:52:50,665 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:52:50,665 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:52:50,665 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'
15:52:52,132 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:52:52,132 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:52:52,132 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:53:00,861 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'
15:53:00,876 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [database.properties]]
15:53:00,876 (o.s.core.env.PropertySourcesPropertyResolver) - Searching for key 'spring.batch.job.enabled' in [class path resource [application.properties]]
15:53:00,876 (o.s.core.env.PropertySourcesPropertyResolver) - Found key 'spring.batch.job.enabled' in [class path resource [application.properties]] with type [String] and value 'false'
...
BatchAutoConfiguration#jobExplorer did not match
- @ConditionalOnMissingBean (types: o.s.batch.core.explore.JobExplorer; SearchStrategy: all) found the following [jobExplorer] (OnBeanCondition)
BatchAutoConfiguration#jobLauncherCommandLineRunner did not match
- @ConditionalOnMissingBean (types: o.s.boot.autoconfigure.batch.JobLauncherCommandLineRunner; SearchStrategy: all) found no beans (OnBeanCondition)
- @ConditionalOnProperty expected 'true' for properties spring.batch.job.enabled (OnPropertyCondition)
BatchAutoConfiguration.JpaBatchConfiguration did not match
- required @ConditionalOnClass classes not found: javax.persistence.EntityManagerFactory (OnClassCondition)
...
15:53:02,225 (o.s.test.context.cache.DefaultCacheAwareContextLoaderDelegate) - Storing ApplicationContext in cache under key [[MergedContextConfiguration@5461ef35 testClass = GetMarkerViaSpringBatchApplicationTest, locations = 'classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml', classes = 'class xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest', contextInitializerClasses = '[]', activeProfiles = '', propertySourceLocations = 'classpath:env.properties, classpath:application.properties, classpath:database.properties', propertySourceProperties = 'spring.batch.job.enabled=false, marker=SELC_ALPHA_DONE, marker_date=2016/06/21, interval=1, times=1, is_fail=true, fail_path=$pkg.out\\failed_alpha_report', contextLoader = 'o.s.boot.test.SpringApplicationContextLoader', parent = [null]]]
15:53:02,256 (o.s.test.context.support.AbstractDirtiesContextTestExecutionListener) - Before test method: context [DefaultTestContext@1733f619 testClass = GetMarkerViaSpringBatchApplicationTest, testInstance = xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest@6769360f, testMethod = testLaunchJob@GetMarkerViaSpringBatchApplicationTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@5461ef35 testClass = GetMarkerViaSpringBatchApplicationTest, locations = 'classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml', classes = 'class xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest', contextInitializerClasses = '[]', activeProfiles = '', propertySourceLocations = 'classpath:env.properties, classpath:application.properties, classpath:database.properties', propertySourceProperties = 'spring.batch.job.enabled=false, marker=SELC_ALPHA_DONE, marker_date=2016/06/21, interval=1, times=1, is_fail=true, fail_path=$pkg.out\\failed_alpha_report', contextLoader = 'o.s.boot.test.SpringApplicationContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null], method annotated with @DirtiesContext [false] with mode [null].
15:53:04,669 (o.s.test.context.support.AbstractDirtiesContextTestExecutionListener) - After test method: context [DefaultTestContext@1733f619 testClass = GetMarkerViaSpringBatchApplicationTest, testInstance = xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest@6769360f, testMethod = testLaunchJob@GetMarkerViaSpringBatchApplicationTest, testException = [null], mergedContextConfiguration = [MergedContextConfiguration@5461ef35 testClass = GetMarkerViaSpringBatchApplicationTest, locations = 'classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml', classes = 'class xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest', contextInitializerClasses = '[]', activeProfiles = '', propertySourceLocations = 'classpath:env.properties, classpath:application.properties, classpath:database.properties', propertySourceProperties = 'spring.batch.job.enabled=false, marker=SELC_ALPHA_DONE, marker_date=2016/06/21, interval=1, times=1, is_fail=true, fail_path=$pkg.out\\failed_alpha_report', contextLoader = 'o.s.boot.test.SpringApplicationContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null], method annotated with @DirtiesContext [false] with mode [null].
15:53:04,685 (o.s.test.context.support.AbstractDirtiesContextTestExecutionListener) - After test class: context [DefaultTestContext@1733f619 testClass = GetMarkerViaSpringBatchApplicationTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@5461ef35 testClass = GetMarkerViaSpringBatchApplicationTest, locations = 'classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml', classes = 'class xxx.myco.batch.client.GetMarkerViaSpringBatchApplicationTest', contextInitializerClasses = '[]', activeProfiles = '', propertySourceLocations = 'classpath:env.properties, classpath:application.properties, classpath:database.properties', propertySourceProperties = 'spring.batch.job.enabled=false, marker=SELC_ALPHA_DONE, marker_date=2016/06/21, interval=1, times=1, is_fail=true, fail_path=$pkg.out\\failed_alpha_report', contextLoader = 'o.s.boot.test.SpringApplicationContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null].
我已阅读 http://forum.spring.io/forum/spring-projects/batch/748038-i-do-not-want-enablebatchprocessing-to-launch-a-job 和 how to stop spring batch scheduled jobs from running at first time when executing the code?,但似乎无法让 jobLauncher不自动启动。
我的理解是application.properties
属性应该被我试图在测试中直接设置的两个地方覆盖,但BatchAutoConfiguration
似乎不尊重该覆盖。
如果我在application.properties
中设置spring.batch.job.enabled=false
(或注释掉该属性)并尝试从@IntegrationTest
或@TestPropertySource
驱动它,它的行为与预期相同。
我对值覆盖的理解不正确吗?
任何帮助将不胜感激。
【问题讨论】:
@ComponentScan
和 @EnableAutoConfiguration
不属于测试类。这只是噪音,因为他们什么都不做。
@DaveSyer 这有效(通知@EnableAutoConfiguration
):@RunWith(SpringJUnit4ClassRunner.class) @EnableBatchProcessing @IntegrationTest("spring.batch.job.enabled=false") @EnableAutoConfiguration @TestPropertySource( location = "classpath:env.properties", "classpath:database.properties") @SpringApplicationConfiguration(classes = GetMarkerViaSpringBatchApplicationTest.class, locations = "classpath:**/GetMarkerViaSpringBatchApplicationTest-context.xml") 公共类GetMarkerViaSpringBatchApplicationTest
@DaveSyer 这不起作用(注意没有@EnableAutoConfiguration
)得到“没有定义名为'jobRepository'的bean”错误:@RunWith(SpringJUnit4ClassRunner.class)@EnableBatchProcessing @IntegrationTest(“spring .batch.job.enabled=false") @TestPropertySource(locations = "classpath:env.properties", "classpath:database.properties") @SpringApplicationConfiguration(classes = GetMarkerViaSpringBatchApplicationTest.class,locations = "classpath :**/GetMarkerViaSpringBatchApplicationTest-context.xml") 公共类 GetMarkerViaSpringBatchApplicationTest
@DaveSyer 这也不起作用(通知已删除@EnableAutoConfiguration
)得到“没有定义名为'jobRepository'的bean”错误:@RunWith(SpringJUnit4ClassRunner.class)@EnableBatchProcessing @IntegrationTest(“ spring.batch.job.enabled=false") @TestPropertySource(locations = "classpath:env.properties", "classpath:database.properties") @SpringApplicationConfiguration public class GetMarkerViaSpringBatchApplicationTest
是的,您正在使用测试类作为配置。我明白了。这不是很常见,我预计它可能会导致其他问题,所以我在评论中指出了这一点。
【参考方案1】:
如果您将application.properties
添加到@TestPropertySource
,那么它最终会覆盖其他内容。如果您使用的是 spring boot,则不需要它。
【讨论】:
是的,这确实是个问题。如果您可以查看对您的@EnableAutoConfiguration
建议的回复 cmets,那将会很有帮助。我怀疑我的问题与将 XML 文件与配置文件的 Java 类混合有关。以上是关于Spring boot Batch 的启动原理- Configuration的主要内容,如果未能解决你的问题,请参考以下文章
Spring Batch/Spring Boot 总是自动启动我的工作
Spring boot Batch - JobLauncherApplicationRunner
spring-boot-starter-jta-atomikos 和 spring-boot-starter-batch
Spring Boot Batch - 排除 JobLauncherCommandLineRunner