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

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

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


欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/2083308.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-07-22
下一篇 2022-07-22

发表评论

登录后才能评论

评论列表(0条)

保存