java - Spring 不实例化具有 Map 或 List 作为属性的 bean
问题描述
我正在使用 Spring Boot 和 Spring Batch 实现一个基本的批处理应用程序。
对于在输入目录中找到的每个文件,都会创建一个步骤,这要归功于MultiResourcePartitioner
<bean id="partitioner"
class="org.springframework.batch.core.partition.support.MultiResourcePartitioner">
<description>
Create a step for each files found in the input directory
</description>
<property name="resources" value="#{resourceProvider.read()}"/>
</bean>
每个步骤由 ItemReader、ItemProcessor 和 ItemWriter 组成。我的问题是 ItemReader,事实上每个 bean 都使用 List/Map 作为 xml 配置中的属性。
我的 ItemReader 如下:
<bean id="itemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
<description>
* resource is set via step scoped late binding (see multiresourcereader)
* strict mode - we expect input files
</description>
<property name="resource" value="#{stepExecutionContext['fileName']}"/>
<property name="strict" value="true"/>
<property name="lineMapper" ref="lineMapper"/>
</bean>
<bean id="lineMapper" class="input.CustomPatternMatchingLineMapper">
<property name="fieldSetMappers">
<map>
<entry key="001*" value-ref="payloadFieldSetMapper"/>
<entry key="000*" value-ref="headerFieldSetMapper"/>
<entry key="999*" value-ref="footerFieldSetMapper"/>
</map>
</property>
<property name="tokenizers">
<map>
<entry key="001*" value-ref="payloadTokenizer"/>
<entry key="000*" value-ref="headerTokenizer"/>
<entry key="999*" value-ref="footerTokenizer"/>
</map>
</property>
</bean>
<bean id="headerTokenizer" class="input.tokenizer.HeaderTokenizer"/>
<bean id="payloadTokenizer" class="input.tokenizer.PayloadTokenizer"/>
<bean id="footerTokenizer" class="input.tokenizer.FooterTokenizer"/>
<bean id="headerFieldSetMapper" class="input.fieldsetmapper.HeaderFieldSetMapper"/>
<bean id="payloadFieldSetMapper" class="input.fieldsetmapper.PayloadFieldSetMapper"/>
<bean id="footerFieldSetMapper" class="input.fieldsetmapper.FooterFieldSetMapper"/>
这是我在 bean 实例化期间在日志中得到的内容
2020-04-21 10:22:32.491 DEBUG 6808 --- [ main] o.s.beans.TypeConverterDelegate : Original ConversionService attempt failed - ignored since PropertyEditor based conversion eventually succeeded
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.util.LinkedHashMap<?, ?>] to type [@org.springframework.lang.Nullable java.util.Map<java.lang.Class<?>, java.lang.Class<java.beans.PropertyEditor>>] for value '{org.springframework.batch.item.file.transform.Range[]=org.springframework.batch.item.file.transform.RangeArrayPropertyEditor}'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [@org.springframework.lang.Nullable java.lang.Class<?>]
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:47) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:191) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:129) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:585) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.AbstractNestablePropertyAccessor.convertForProperty(AbstractNestablePropertyAccessor.java:604) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:219) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1748) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1704) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1444) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207) ~[spring-beans-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:171) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:706) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:532) ~[spring-context-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) ~[spring-boot-2.2.6.RELEASE.jar:2.2.6.RELEASE]
at Lanceur.main(Lanceur.java:40) ~[classes/:na]
Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [@org.springframework.lang.Nullable java.lang.Class<?>]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.core.convert.support.MapToMapConverter.convertKey(MapToMapConverter.java:122) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.core.convert.support.MapToMapConverter.convert(MapToMapConverter.java:84) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) ~[spring-core-5.2.5.RELEASE.jar:5.2.5.RELEASE]
... 23 common frames omitted
这是该过程无限期挂起的地方:
2020-04-21 10:22:36.261 DEBUG 6808 --- [cTaskExecutor-4] o.s.batch.core.scope.StepScope : Creating object in scope=step, name=scopedTarget.itemReader
供您参考,如果我使用另一个 LineMapper,我不会遇到这个问题。
另一个信息,因为我使用的是 Spring Boot,所以我必须覆盖 StepScope 定义才能使用该scope="step"
属性
<bean id="stepScope" class="org.springframework.batch.core.scope.StepScope">
<property name="autoProxy" value="true"/>
</bean>
spring.main.allow-bean-definition-overriding=true
编辑
这是我必须映射的行的示例,它的关联 POJO 和它实现的接口:
001234577589NNNNNN FFF M
@Data
public class Payload implements Element {
private String debLine;
private String id;
private String name;
private String firstName;
private String gender;
private int numLine;
}
public interface Element {
String getDebLine();
int getNumLine();
void setNumLine(int numLine);
}
解决方案
推荐阅读
- python - 无法在带有 Python 的 VS Code 中使用终端
- sharepoint - Sharepoint Online 编辑但不发布权限
- r - 计算两个向量之间相同值的数量
- ios - 具有自定义框架的 iOS 应用程序 Appstore 提交问题
- navigation - 如何将具有多个值的非二进制占用网格映射到 ROS 中的成本图?
- c++ - 调用 erase() 函数是否会在元素被擦除之前更改迭代器值?
- javascript - history.back() 在 Firefox 和 Internet Explorer 中不起作用,但在 google chrome 中起作用
- sql - SQL Server 日期格式到具有特定格式的 Datetimeoffset
- python - 单击按钮时如何停止线程(QRunnable)?
- loops - 使用 runas 命令提示符 (cmd) 循环