我正在开发几个Spring Batch应用程序,这些应用程序从具有大量列的映射结果集对象创建平面文件。
编写Field Extactor的“names”属性和xml中的Line Aggregators的“format”属性很麻烦且容易出错,因此我构建了一个包含字段列表的组件,并且有一个返回String的公共方法字段名称数组和另一个将所有格式说明符作为字符串返回的公共方法。以下是简化示例:
public class Field {
private String fieldName; // e.g., "firstName"
private String format; // e.g., "%-16s"
// getters/setters omitted here
}
@component
public abstract class FieldList extends ArrayList {
public FieldList () {
}
public String[] getFieldNameArray() {
ArrayList<String> names = new ArrayList<String>();
for (int i = 0; i < this.size(); i++) {
names.add(this.get(i).getFieldName());
}
return (String[]) names.toArray();
}
public String getFormatStrings() {
StringBuffer sb = new StringBuffer ();
for (int i = 0; i < this.size(); i++) {
sb.appeng(this.get(i).getFormat());
}
return (String[]) names.toArray();
}
}
@Component
public class EmployeeFieldList extends FieldList {
public EmployeeFieldList () {
super();
this.add(new Field("empId", "%-8s"));
this.add(new Field("firstName","%-16s"));
// etc., etc. Some classes have 50+ fields
}
}
在XML配置中我有:
<bean id="employeeFieldList" class="com.stuff.EmployeeFieldList" />
<bean id="employeeFileItemWriter"
class="o.s.b.item.file.FlatFileItemWriter" >
<property name="resource" value="file:${strRunFileName}" />
<property name="lineAggregator">
<bean class="o.s.b.item.file.transform.FormatterLineAggregator"
<property name="fieldExtractor">
<bean
class="o.s.b.item.file.transform.BeanWrapperFieldExtractor"
<property name="names" ref="fieldNameArray" />
</bean>
</property >
<property name="format" ref="formatStrings" />
</bean>
</property >
</bean>
组件符合javabean api,所以一旦我在xml中定义组件,我也应该能够引用它的公共成员,对吗?
然而,这不起作用。在日志中我看到了:
Error creating bean with name
'o.s.b.item.file.transform.BeanWrapperFieldExtractor#60cbf9bd'
defined in class path resource [spring/module-context.xml]:
Cannot resolve reference to bean 'fieldNameArray' while setting bean
property 'names';
nested exception is o.s.b.factory.NoSuchBeanDefinitionException:
**No bean named 'fieldNameArray' is defined**
我尝试过应用几种符号约定,但仍然会收到错误,所以看起来只能对bean进行引用,而不是它们的公共属性。或者我错过了什么?
答案 0 :(得分:0)
正确。 Spring的ref
属性引用了一个bean id
。
话虽如此,我实际上建议采用略有不同的方法。我建议您为FactoryBean
创建一个FieldExtractor
,而不是创建一个返回名称字符串的组件。这可以用于封装您想要的BeanWrapperFieldExtractor
的创建。
一个例子看起来像这样:
public class ComplexBeanWrapperFieldExtractorFactory implements FactoryBean<FieldExtractor> {
public FieldExtractor getObject() {
// put logic here to generate your string
// put your logic here to actually create an instance of a BeanWrapperFieldExtractor configured as you need
// return the instance you just created.
}
}
使用上面的代码,您可以按如下方式配置阅读器:
<bean id="fieldExtractorFactory" class="ComplexBeanWrapperFieldExtractorFactory/>
<bean id="employeeFileItemWriter"
class="o.s.b.item.file.FlatFileItemWriter" >
<property name="resource" value="file:${strRunFileName}" />
<property name="lineAggregator">
<bean class="o.s.b.item.file.transform.FormatterLineAggregator"
<property name="fieldExtractor" ref="fieldExtractorFactory"/>
<property name="format" ref="formatStrings" />
</bean>
</property >
</bean>