2012-03-22 91 views
6

我不知道为什么在Spring DI下面bean定义工作(我用bean instantiation with a static factory method和番石榴的Suppliers.ofInstance):通用工厂方法

<bean id="keySupplier" class="com.google.common.base.Suppliers" 
    factory-method="ofInstance"> 
    <constructor-arg> 
    <value type="java.lang.String">someReallyLongValue <!-- note line break here --> 
    </value> 
    </constructor-arg> 
</bean> 

但是这一次没有:

<bean id="keySupplier" class="com.google.common.base.Suppliers" 
    factory-method="ofInstance"> 
    <constructor-arg type="java.lang.String" value="someReallyLongValue" /> 
</bean> 

它引发以下异常:

org.springframework.beans.factory.BeanCreationException:Error creatin克豆名为“userRepo”类路径资源定义:
(...)
不合格依赖通过构造器参数表示与式[java.lang.Object中]的索引0:
歧义工厂方法参数类型 - 没有你指定了正确的bean引用作为工厂方法参数?

的问题是,在我的情况下,当我用很长的字符串第一个bean定义为一个值我的编辑断裂线串的最后一个字符,这将导致该字符串与额外的空格传递给Suppliers.ofInstance后并在结果它打破了我的代码。

第二个定义对于空格更加严格,但是,令人惊讶的是,它不起作用(尽管类型是在type属性中指定的,它可能不适用泛型类型)。

我可以强迫Spring忽略<value>标记中的空白吗?

或者我正确使用<constructor-arg type="java.lang.String" value="someReallyLongValue" />?或者我应该提交一个问题,因为它是一个Spring错误?

我不想对字符串做任何假设(即在这里使用string.trim())。

+0

首先,将您的XML编辑器配置为不自动插入换行符。如果没有这样的选项,改变编辑器;) – 2012-03-27 08:05:46

+0

@YvesMartin我可以配置我的编辑器来这样做,但如果其他人将来做格式化(Eclipse中简单的'CSf'),我不喜欢应用程序将因此而被打破。 – Xaerxess 2012-03-27 08:50:11

+1

这样的问题将永远存在。您应该将这些文本信息移动到属性文件中。 – 2012-03-27 09:27:54

回答

0

我会建议使用属性文件,然后在定义

使用属性,但这并不说明你观察到的行为。

+0

其实我选择'供应商'不是'字符串'作为依赖项,因为我要用供应商(memoize提供的值,从注册表/属性文件等获取String)做更高级的东西。这个具体的例子是'keySupplier' bean的模拟实现,这就是为什么我在这里使用'Suppliers.ofInstance'静态工厂,为什么我对bean创建失败感到好奇。 – Xaerxess 2012-03-22 12:24:39

0

不是100%肯定,但尝试

<value index="0" [...] 

不知道你的代码是什么样子,但你把你的构造ARGS命令,除非您指定的位置不被考虑。如果你有多个构造函数,这可能会搞砸了。

+0

不,这里没有帮助 - 得到同样的例外。顺便说一句,你的意思是'',对吧? – Xaerxess 2012-03-23 07:58:38

6

根据reference documentation about constructor resolution,这两种配置在Spring中并不涉及相同的执行路径。失败来自用于this instanceOf method的泛型,它声明Object作为方法参数。

弹簧必须执行以下任务成功:

  • 找到根据的论点
  • 转换XML文本值转换成Java正确的方法对象要么得益于明确的type声明或方法参数的类型时,根据index用于

所涉及的逻辑是在ConstructorArgumentValues保持器的方法和getArgumentValue在两个getIndexedArgumentValue一个d getGenericArgumentValue。根据可用信息,两种方法都使用测试来拒绝ValueHolder

在第二种配置方案中,使用索引检测并拒绝该值,因为所需类型StringObject不完全匹配。该测试使用ClassUtils.matchesTypeName来完成,它不检查类型层次结构。

在第一种配置方案中,值持有者已准备好使用String对象,并且泛型参数机制同意,因为该值可分配给检测到的方法参数类型。

理论上讲,下面的表达式应该起作用,因为提供了类型来从值中生成对象,并且提供了索引以避免任何猜测,即使只有一个方法匹配。

<constructor-arg index="0" type="java.lang.String" value="queueName" /> 

坏运气,它没有改善任何东西,仍然使用相同的执行路径。我真的认为春季改善是必需的。你可以创建一个JIRA ticket

+1

''和''之间的区别是否记录在某处或您检查了源代码? – Xaerxess 2012-03-27 09:55:19

+1

我已经创建了[ticket](https://jira.springsource.org/browse/SPR-9270),现在我会等待错误得到确认。 – Xaerxess 2012-03-27 18:01:28

+0

我不认为它是一个错误,但作为一种改进。顺便说一下,推荐的表单是使用“”标签! – 2012-03-27 21:23:33