2015-06-03 43 views
0

我正在開發幾個Spring批處理應用程序,這些應用程序可以從具有大量列的映射結果集對象中創建平面文件。spring批處理 - 如何在XML中引用bean屬性

在xml中對Field Extactor的「names」屬性和Line Aggregators的「format」屬性進行編碼很麻煩且容易出錯,所以我構建了一個包含字段列表並具有公共方法的組件,以返回字符串數組的字符串名稱和另一個公共方法將所有格式說明符作爲字符串返回。下面是簡單的例子:

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** 

我試着將一些符號約定,但仍然得到錯誤,所以會出現引用只能是豆製成的,而不是他們的公共屬性。或者我錯過了什麼?

回答

0

正確。 Spring的ref屬性是指一個bean id

這就是說,我實際上會推薦一個稍微不同的方法。我建議您爲FieldExtractor創建一個FactoryBean,而不是創建返回一個名稱字符串的組件。這可以用來封裝創建的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> 
+0

謝謝,邁克爾。同時,我曾嘗試子類化FieldExtractor和LineAggregator,以便我可以注入EmployeeFieldList的引用。然而,在我的子類可以設置names屬性之前,SB框架似乎在FieldExtractor超類上觸發了afterPropertySet()方法,所以它總是拋出IllegalArgumentException。我會嘗試工廠的方法,看看它是否解決了這個問題。 順便說一句,是te SB框架後續版本支持的屬性引用(通過點符號或其他方式)嗎? – JeffInTampa