可以为<constructor-arg>元素指定type和index属性,帮助Spring查找预期的构造程序。最新版的Spring也可以使用name属性。
(1)第一种情况
/*
* Copyright 2013-2015
*/
package com.jackie.codeproject.springrecipesnote.springioc;
/**
* Title: SequenceGenerator.java 类的功能说明
*
* @author jackie
* @since Apr 13, 2013 12:56:57 PM
* @version V1.0
*/
public class SequenceGenerator {
/**
* @Fields prefix : 前缀
*/
private String prefix;
/**
* @Fields suffix : 后缀
*/
private String suffix;
/**
* @Fields initial : 初始值
*/
private int initial;
/**
* @Fields counter : 计数器
*/
private int counter;
/**
* 获取序列号,声明为同步,使其成为线程安全的方法
* @author jackie
* @date Apr 13, 2013
* @return
* @return String
*/
public synchronized String getSquence() {
StringBuffer buffer = new StringBuffer();
buffer.append(prefix);
buffer.append(initial + counter++);
buffer.append(suffix);
return buffer.toString();
}
/**
* <p>Title: </p>
* <p>Description:构造函数1 </p>
* @param prefix
* @param suffix
* @param initial
*/
public SequenceGenerator(String prefix, String suffix, int initial) {
this.prefix = prefix;
this.suffix = suffix;
this.initial = initial;
}
/**
* <p>Title: </p>
* <p>Description:构造函数2 </p>
* @param prefix
* @param suffix
*/
public SequenceGenerator(String prefix, String suffix) {
this.prefix = prefix;
this.suffix = suffix;
}
/**
* <p>Title: </p>
* <p>Description:构造函数3 </p>
* @param prefix
* @param initial
*/
public SequenceGenerator(String prefix, int initial) {
this.prefix = prefix;
this.initial = initial;
}
/**
* @param prefix
* the prefix to set
*/
public void setPrefix(String prefix) {
this.prefix = prefix;
}
/**
* @param suffix
* the suffix to set
*/
public void setSuffix(String suffix) {
this.suffix = suffix;
}
/**
* @param initial
* the initial to set
*/
public void setInitial(int initial) {
this.initial = initial;
}
}
Bean配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-3.2.xsd">
<bean id="sequenceGenerator" class="com.jackie.codeproject.springrecipesnote.springioc.SequenceGenerator">
<constructor-arg value="30" />
<constructor-arg value="100000" />
<property name="suffix" value="A" />
</bean>
</beans>
测试程序:
// 使用ClassPathXmlApplicationContext是ApplicationContext接口的一个实现,它可以从classpath中装入一个XML配置文件 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml"); // 使用getBean方法并为其传递配置的唯一的Bean名称,其返回类型为Object,须强制转型。 SequenceGenerator sequenceGenerator = (SequenceGenerator) applicationContext.getBean("sequenceGenerator"); System.out.println(sequenceGenerator.getSquence()); System.out.println(sequenceGenerator.getSquence());
输出结果:300A
301A
分析:出现这种结果的原因是调用了带有prefix和suffix参数的构造程序,而不是带有prefix和initial参数的。因为Spring默认将两个参数都解析为String类型,第一个构造程序不需要类型转换,所以被认定最合适。为了指定参数的预期类型,你必须设置<constructor-arg>中的type属性。
<bean id="sequenceGenerator" class="com.jackie.codeproject.springrecipesnote.springioc.SequenceGenerator">
<constructor-arg type="java.lang.String" value="30" />
<constructor-arg type="int" value="100000" />
<property name="suffix" value="A" />
</bean>
(2)第二种情况
在SequenceGenerator中再添加以下构造函数:
/** * <p>Title: </p> * <p>Description: </p> * @param suffix * @param initial */ public SequenceGenerator(int initial, String suffix) { this.suffix = suffix; this.initial = initial; }
修改Bean配置文件:
<bean id="sequenceGenerator" class="com.jackie.codeproject.springrecipesnote.springioc.SequenceGenerator">
<constructor-arg type="int" value="100000" />
<constructor-arg type="java.lang.String" value="A" />
<property name="prefix" value="30" />
</bean>
书上说再次运行测试程序可能得到正确结果,或者得到以下意外结果:
30100000null
30100000null
原因是Spring认为SequenceGenerator(String prefix, int initial) 和SequenceGenerator(int initial, String suffix)这两个构造函数是一样的,不会考虑参数出现在XML中的顺序,所以会造成歧义。但是我本人的程序跑起来都是使用的SequenceGenerator(int initial, String suffix),不知是不是最新版的Spring考虑了参数在XML文件中的位置,如有知道的牛人麻烦告知一声。
可以使用<constructor-arg>的index属性明确指出参数索引值。设置了type和Index属性,Spring就能够准确的为Bean找到预期的构造函数。
<bean id="sequenceGenerator" class="com.jackie.codeproject.springrecipesnote.springioc.SequenceGenerator">
<constructor-arg type="int" index="0" value="100000" />
<constructor-arg type="java.lang.String" index="1" value="A" />
<property name="prefix" value="30" />
</bean>
最简单的还是使用<constructor-arg>的name属性:
<bean id="sequenceGenerator" class="com.jackie.codeproject.springrecipesnote.springioc.SequenceGenerator">
<constructor-arg name="initial" value="100000" />
<constructor-arg name="suffix" value="A" />
<property name="prefix" value="30" />
</bean>