创建名称为 'batchPropertyPostProcessor' 的 bean 时,批处理作业初始化因错误而失败
Batch job initialization fails on error while creating bean with name 'batchPropertyPostProcessor'
我正在尝试使用 JSR-352 API 和 Spring Batch 3.0.4 作为实现来实现示例批处理应用程序。
创建名为 'batchPropertyPostProcessor':
的 bean 时,批处理作业在初始化阶段因错误而失败
Exception in thread "main" javax.batch.operations.JobStartException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'batchPropertyPostProcessor': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.batch.core.jsr.launch.support.BatchPropertyBeanPostProcessor.setBatchPropertyContext(org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext); nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [dataListingStepListener] for bean with name 'scopedTarget.dataListingStepListener' defined in null; nested exception is java.lang.ClassNotFoundException: dataListingStepListener
at org.springframework.batch.core.jsr.launch.JsrJobOperator.start(JsrJobOperator.java:637)
at x98.BatchRunner.main(BatchRunner.java:18)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'batchPropertyPostProcessor': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.batch.core.jsr.launch.support.BatchPropertyBeanPostProcessor.setBatchPropertyContext(org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext); nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [dataListingStepListener] for bean with name 'scopedTarget.dataListingStepListener' defined in null; nested exception is java.lang.ClassNotFoundException: dataListingStepListener
at org.springframework.batch.core.jsr.configuration.support.SpringAutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(SpringAutowiredAnnotationBeanPostProcessor.java:262)
at org.springframework.batch.core.jsr.configuration.support.JsrAutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(JsrAutowiredAnnotationBeanPostProcessor.java:30)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:232)
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:618)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:467)
at org.springframework.batch.core.jsr.launch.JsrJobOperator.start(JsrJobOperator.java:635)
... 1 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.batch.core.jsr.launch.support.BatchPropertyBeanPostProcessor.setBatchPropertyContext(org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext); nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [dataListingStepListener] for bean with name 'scopedTarget.dataListingStepListener' defined in null; nested exception is java.lang.ClassNotFoundException: dataListingStepListener
at org.springframework.batch.core.jsr.configuration.support.SpringAutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(SpringAutowiredAnnotationBeanPostProcessor.java:575)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.batch.core.jsr.configuration.support.SpringAutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(SpringAutowiredAnnotationBeanPostProcessor.java:259)
... 13 more
Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [dataListingStepListener] for bean with name 'scopedTarget.dataListingStepListener' defined in null; nested exception is java.lang.ClassNotFoundException: dataListingStepListener
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1325)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:594)
at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:526)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:387)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:354)
at org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors(BeanFactoryUtils.java:187)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1002)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:960)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
at org.springframework.batch.core.jsr.configuration.support.SpringAutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(SpringAutowiredAnnotationBeanPostProcessor.java:532)
... 15 more
Caused by: java.lang.ClassNotFoundException: dataListingStepListener
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:247)
at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:395)
at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1346)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1317)
... 24 more
我的批次运行纳:
public class BatchRunner {
public static void main(String[] args) {
System.setProperty("JSR-352-BASE-CONTEXT", "x98_batch_local.xml");
Properties jobParameters = new Properties();
jobParameters.put("message", "Hello!");
JobOperator jobOperator = BatchRuntime.getJobOperator();
jobOperator.start("x98SampleJob", jobParameters);
}
}
我的 sampleJob 定义:
<?xml version="1.0" encoding="UTF-8"?>
<job id="x98SampleJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/jobXML_1_0.xsd"
version="1.0">
<step id="simple" next="dataListing">
<batchlet ref="simpleBatchlet">
<properties>
<property name="message" value="#{jobParameters['message']}" />
</properties>
</batchlet>
</step>
<step id="dataListing">
<listeners>
<listener ref="dataListingStepListener"/>
</listeners>
<chunk item-count="3">
<reader ref="dataListingItemReader" />
<processor ref="dataListingItemProcessor"/>
<writer ref="dataListingItemWriter"/>
</chunk>
</step>
</job>
我的 Spring bean 配置 reader、编写器、处理器和侦听器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">
<import resource="classpath*:x98_services.xml"/>
<bean name="simpleBatchlet" class="x98.batch.SimpleBatchlet"/>
<bean name="dataListingItemProcessor" class="x98.batch.DataListingItemProcessor"/>
<bean name="dataListingItemReader" class="x98.batch.DataListingItemReader">
<property name="tx98DatasService" ref="tx98DatasService"/>
<property name="tx98StructureService" ref="tx98StructureService"/>
</bean>
<bean name="dataListingItemWriter" class="x98.batch.DataListingItemWriter"/>
<bean name="dataListingStepListener" class="x98.batch.DataListingStepListener">
<property name="tx98StatusService" ref="tx98StatusService"/>
</bean>
</beans>
Reader、编写器和处理器由 Spring 实例化并在作业 运行 中正确使用。当我将侦听器添加到作业定义时,它停止工作。
我调试了代码,发现 dataListingStepListener bean 在 Spring 上下文中被初始化。我不明白为什么对侦听器 (<listener ref="dataListingStepListener"/>
) 的引用未被识别为 Spring bean,而 Spring 正在尝试加载名为 "dataListingStepListener" 的 class。
我的配置可以吗?我做错了什么吗?
阅读要点后,有几点注意事项:
作业特定 beans 必须在子上下文中
Spring Batch 的 JSR-352 上下文管理通过 parent/child 关系工作。父上下文由 baseContext.xml 定义,或者可以像您通过系统 属性 JSR-352-BASE-CONTEXT
所做的那样被覆盖。该上下文旨在仅用于基础结构 bean,并且不由 JSR-352 post 处理器处理 属性 注入之类的事情。你说 "When I added listener to job definition it stopped to work." 如果你仔细观察,当工作 运行 时,你的 属性 没有被注入 SimpleBatchlet
(消息是 null
)。
原因是如果你想运行多个作业,你不应该需要创建多个JobRepository
实例,多个连接池等,所以我们只bootstrap 父上下文一次。因为我们只 bootstrap 它一次,所以我们当时没有要注入的作业属性之类的值(它们可能会因作业而异)。
因此,所有特定于作业的 bean 都应该在子上下文中。
为 JSR-352 定义子上下文
JSR-352 提供三种不同的方式来处理 bean 创建:
- 内联 - 在作业 XML 的工件定义的
ref
属性中提供完全限定的 class 名称,它将使用无参数构造函数创建。
- batch.xml - batch.xml 文件提供了一种通过为 class 名称提供别名来简化上述概念的方法。
- 特定于 DI 的实现(在本例中为 Spring DI)- Spring Batch 的 JSR-352 实现提供了使用 Spring 用于创建 bean 的 DI 工具。
这样,我们就将控制权交给您来创建 bean 实例。默认情况下,在 Spring 中,bean 是在启动时创建的单例。但是,Spring Batch 提供范围(step
或 job
)以允许后期绑定属性。如果你想要 属性 注入,一个 bean 必须被定义为 step
范围(SimpleBatchlet
不是,这就是为什么消息是 null
第一个 运行)。
那么在定义工作上下文时,如何实现 Spring DI 和基于标准的 JSR-352 之间的关注点分离?简单的。将作业 XML 导入 Spring XML 并将 Spring XML 名称传递给要启动的 JobOperator
。在你的情况下,而不是:
public static void main(String[] args) {
System.setProperty("JSR-352-BASE-CONTEXT", "x98_batch_local.xml");
Properties jobParameters = new Properties();
jobParameters.put("message", "Hello!");
JobOperator jobOperator = BatchRuntime.getJobOperator();
jobOperator.start("x98SampleJob", jobParameters);
}
将以下内容添加到您的 x98_batch_local.xml:
<import resource="classpath*:x98SampleJob.xml"/>
然后通过以下方式执行您的工作:
public static void main(String[] args) {
Properties jobParameters = new Properties();
jobParameters.put("message", "Hello!");
JobOperator jobOperator = BatchRuntime.getJobOperator();
jobOperator.start("x98_batch_local.xml", jobParameters);
}
上述调整和将您的 SimpleBatchlet
设置为步进范围将使您的作业达到预期的 运行。
注意: 由于这个问题,我创建了问题 BATCH-2388 以更好地记录上面讨论的上下文注意事项。
我正在尝试使用 JSR-352 API 和 Spring Batch 3.0.4 作为实现来实现示例批处理应用程序。
创建名为 'batchPropertyPostProcessor':
的 bean 时,批处理作业在初始化阶段因错误而失败Exception in thread "main" javax.batch.operations.JobStartException: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'batchPropertyPostProcessor': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.batch.core.jsr.launch.support.BatchPropertyBeanPostProcessor.setBatchPropertyContext(org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext); nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [dataListingStepListener] for bean with name 'scopedTarget.dataListingStepListener' defined in null; nested exception is java.lang.ClassNotFoundException: dataListingStepListener
at org.springframework.batch.core.jsr.launch.JsrJobOperator.start(JsrJobOperator.java:637)
at x98.BatchRunner.main(BatchRunner.java:18)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'batchPropertyPostProcessor': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.batch.core.jsr.launch.support.BatchPropertyBeanPostProcessor.setBatchPropertyContext(org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext); nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [dataListingStepListener] for bean with name 'scopedTarget.dataListingStepListener' defined in null; nested exception is java.lang.ClassNotFoundException: dataListingStepListener
at org.springframework.batch.core.jsr.configuration.support.SpringAutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(SpringAutowiredAnnotationBeanPostProcessor.java:262)
at org.springframework.batch.core.jsr.configuration.support.JsrAutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(JsrAutowiredAnnotationBeanPostProcessor.java:30)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.context.support.PostProcessorRegistrationDelegate.registerBeanPostProcessors(PostProcessorRegistrationDelegate.java:232)
at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:618)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:467)
at org.springframework.batch.core.jsr.launch.JsrJobOperator.start(JsrJobOperator.java:635)
... 1 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void org.springframework.batch.core.jsr.launch.support.BatchPropertyBeanPostProcessor.setBatchPropertyContext(org.springframework.batch.core.jsr.configuration.support.BatchPropertyContext); nested exception is org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [dataListingStepListener] for bean with name 'scopedTarget.dataListingStepListener' defined in null; nested exception is java.lang.ClassNotFoundException: dataListingStepListener
at org.springframework.batch.core.jsr.configuration.support.SpringAutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(SpringAutowiredAnnotationBeanPostProcessor.java:575)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
at org.springframework.batch.core.jsr.configuration.support.SpringAutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(SpringAutowiredAnnotationBeanPostProcessor.java:259)
... 13 more
Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [dataListingStepListener] for bean with name 'scopedTarget.dataListingStepListener' defined in null; nested exception is java.lang.ClassNotFoundException: dataListingStepListener
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1325)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:594)
at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:526)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:387)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:354)
at org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors(BeanFactoryUtils.java:187)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1002)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:960)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:858)
at org.springframework.batch.core.jsr.configuration.support.SpringAutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(SpringAutowiredAnnotationBeanPostProcessor.java:532)
... 15 more
Caused by: java.lang.ClassNotFoundException: dataListingStepListener
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:247)
at org.springframework.beans.factory.support.AbstractBeanDefinition.resolveBeanClass(AbstractBeanDefinition.java:395)
at org.springframework.beans.factory.support.AbstractBeanFactory.doResolveBeanClass(AbstractBeanFactory.java:1346)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveBeanClass(AbstractBeanFactory.java:1317)
... 24 more
我的批次运行纳:
public class BatchRunner {
public static void main(String[] args) {
System.setProperty("JSR-352-BASE-CONTEXT", "x98_batch_local.xml");
Properties jobParameters = new Properties();
jobParameters.put("message", "Hello!");
JobOperator jobOperator = BatchRuntime.getJobOperator();
jobOperator.start("x98SampleJob", jobParameters);
}
}
我的 sampleJob 定义:
<?xml version="1.0" encoding="UTF-8"?>
<job id="x98SampleJob" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/jobXML_1_0.xsd"
version="1.0">
<step id="simple" next="dataListing">
<batchlet ref="simpleBatchlet">
<properties>
<property name="message" value="#{jobParameters['message']}" />
</properties>
</batchlet>
</step>
<step id="dataListing">
<listeners>
<listener ref="dataListingStepListener"/>
</listeners>
<chunk item-count="3">
<reader ref="dataListingItemReader" />
<processor ref="dataListingItemProcessor"/>
<writer ref="dataListingItemWriter"/>
</chunk>
</step>
</job>
我的 Spring bean 配置 reader、编写器、处理器和侦听器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd">
<import resource="classpath*:x98_services.xml"/>
<bean name="simpleBatchlet" class="x98.batch.SimpleBatchlet"/>
<bean name="dataListingItemProcessor" class="x98.batch.DataListingItemProcessor"/>
<bean name="dataListingItemReader" class="x98.batch.DataListingItemReader">
<property name="tx98DatasService" ref="tx98DatasService"/>
<property name="tx98StructureService" ref="tx98StructureService"/>
</bean>
<bean name="dataListingItemWriter" class="x98.batch.DataListingItemWriter"/>
<bean name="dataListingStepListener" class="x98.batch.DataListingStepListener">
<property name="tx98StatusService" ref="tx98StatusService"/>
</bean>
</beans>
Reader、编写器和处理器由 Spring 实例化并在作业 运行 中正确使用。当我将侦听器添加到作业定义时,它停止工作。
我调试了代码,发现 dataListingStepListener bean 在 Spring 上下文中被初始化。我不明白为什么对侦听器 (<listener ref="dataListingStepListener"/>
) 的引用未被识别为 Spring bean,而 Spring 正在尝试加载名为 "dataListingStepListener" 的 class。
我的配置可以吗?我做错了什么吗?
阅读要点后,有几点注意事项:
作业特定 beans 必须在子上下文中
Spring Batch 的 JSR-352 上下文管理通过 parent/child 关系工作。父上下文由 baseContext.xml 定义,或者可以像您通过系统 属性 JSR-352-BASE-CONTEXT
所做的那样被覆盖。该上下文旨在仅用于基础结构 bean,并且不由 JSR-352 post 处理器处理 属性 注入之类的事情。你说 "When I added listener to job definition it stopped to work." 如果你仔细观察,当工作 运行 时,你的 属性 没有被注入 SimpleBatchlet
(消息是 null
)。
原因是如果你想运行多个作业,你不应该需要创建多个JobRepository
实例,多个连接池等,所以我们只bootstrap 父上下文一次。因为我们只 bootstrap 它一次,所以我们当时没有要注入的作业属性之类的值(它们可能会因作业而异)。
因此,所有特定于作业的 bean 都应该在子上下文中。
为 JSR-352 定义子上下文
JSR-352 提供三种不同的方式来处理 bean 创建:
- 内联 - 在作业 XML 的工件定义的
ref
属性中提供完全限定的 class 名称,它将使用无参数构造函数创建。 - batch.xml - batch.xml 文件提供了一种通过为 class 名称提供别名来简化上述概念的方法。
- 特定于 DI 的实现(在本例中为 Spring DI)- Spring Batch 的 JSR-352 实现提供了使用 Spring 用于创建 bean 的 DI 工具。
这样,我们就将控制权交给您来创建 bean 实例。默认情况下,在 Spring 中,bean 是在启动时创建的单例。但是,Spring Batch 提供范围(step
或 job
)以允许后期绑定属性。如果你想要 属性 注入,一个 bean 必须被定义为 step
范围(SimpleBatchlet
不是,这就是为什么消息是 null
第一个 运行)。
那么在定义工作上下文时,如何实现 Spring DI 和基于标准的 JSR-352 之间的关注点分离?简单的。将作业 XML 导入 Spring XML 并将 Spring XML 名称传递给要启动的 JobOperator
。在你的情况下,而不是:
public static void main(String[] args) {
System.setProperty("JSR-352-BASE-CONTEXT", "x98_batch_local.xml");
Properties jobParameters = new Properties();
jobParameters.put("message", "Hello!");
JobOperator jobOperator = BatchRuntime.getJobOperator();
jobOperator.start("x98SampleJob", jobParameters);
}
将以下内容添加到您的 x98_batch_local.xml:
<import resource="classpath*:x98SampleJob.xml"/>
然后通过以下方式执行您的工作:
public static void main(String[] args) {
Properties jobParameters = new Properties();
jobParameters.put("message", "Hello!");
JobOperator jobOperator = BatchRuntime.getJobOperator();
jobOperator.start("x98_batch_local.xml", jobParameters);
}
上述调整和将您的 SimpleBatchlet
设置为步进范围将使您的作业达到预期的 运行。
注意: 由于这个问题,我创建了问题 BATCH-2388 以更好地记录上面讨论的上下文注意事项。