Spring DI中的通用工厂方法

时间:2012-03-22 11:01:17

标签: java spring dependency-injection

我想知道为什么在Spring DI中以下bean定义有效(我使用bean instantiation with a static factory method和Guava的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:在类路径资源中定义名为'userRepo'的bean时出错:
  (...)
  通过带有[java.lang.Object]类型的索引0的构造函数参数表示的不满意依赖性:
  不明确的工厂方法参数类型 - 您是否将正确的bean引用指定为工厂方法参数?

问题是,在我的情况下,当我使用第一个bean定义并使用非常长的字符串作为值时,我的编辑器会在字符串的最后一个字符后断行,这会导致字符串与其他空格一起传递Suppliers.ofInstance,结果它破坏了我的代码。

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

我可以强制Spring以某种方式忽略<value>标记中的空格吗?

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

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

3 个答案:

答案 0 :(得分:6)

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

Spring必须完成以下任务才能成功:

  • 根据参数找到正确的方法
  • 在使用type时,感谢显式index声明或基于方法参数类型,将XML文字值转换为Java对象

所涉及的逻辑位于方法getArgumentValue以及getIndexedArgumentValuegetGenericArgumentValue中的ConstructorArgumentValues持有者中。两种方法都使用测试根据可用信息拒绝ValueHolder

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

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

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

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

运气不好,它没有改进任何东西,仍然使用相同的执行路径。我真的认为需要Spring改进。你可以创建一个JIRA ticket

答案 1 :(得分:0)

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

中使用该属性

但这并不能解释您观察到的行为。

答案 2 :(得分:0)

不是100%肯定,但尝试

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

不确定您的代码是什么样的,但除非您指定位置,否则不会考虑放置构造函数args的顺序。如果你有多个构造函数,这可能会搞砸了。