我想知道为什么在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()
)。
答案 0 :(得分:6)
根据reference documentation about constructor resolution,这两个配置在Spring中不涉及相同的执行路径。失败来自用于this instanceOf method的泛型,它将Object
声明为方法参数。
Spring必须完成以下任务才能成功:
type
时,感谢显式index
声明或基于方法参数类型,将XML文字值转换为Java对象所涉及的逻辑位于方法getArgumentValue
以及getIndexedArgumentValue
和getGenericArgumentValue
中的ConstructorArgumentValues持有者中。两种方法都使用测试根据可用信息拒绝ValueHolder
。
在第二种配置方案中,使用索引检测并拒绝该值,因为所需类型String
与Object
不完全匹配。此测试使用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的顺序。如果你有多个构造函数,这可能会搞砸了。