阅读 54

Spring攻略学习笔记(4)解决构造程序歧义

 可以为<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>


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐