我想通过xml配置文件创建两个相同类的bean。该类有一个带有注释的setter,可以用spring填充。在其中一个bean定义中,我还手动提供值以覆盖注释中的一个。但是当我这样做时,spring不再处理注释布线。
以下是展示此效果的最小代码,为简单起见使用了@Value
,但与@Autowired
相同:
import org.springframework.beans.factory.annotation.Value;
import javax.annotation.PostConstruct;
public class AutowireTest {
public String testField;
@PostConstruct
public void init() {
if (testField == null)
throw new RuntimeException("FAIL");
}
@Value("default")
public void setTestField(String testField) {
this.testField = testField;
}
}
和spring config:
<bean id="au_test1" class="AutowireTest">
<property name="testField" value="manual"/>
</bean>
<bean id="au_test2" class="AutowireTest"/>
如果我删除<property name="testField" value="manual"/>
,则两个bean都会收到“默认”。如果它在那里第二个bean抛出一个异常。我查看了spring代码,AutowiredAnnotationBeanPostProcessor
正在使用injectionMetadataCache,其中类是注入元数据的键,这意味着为一个bean设置特定属性会禁用其他实例的自动装配。
知道为什么会这样吗?如何实现类似的效果,不一定是字符串值,也适用于对象bean?
编辑:
我希望有一个属性,有多个匹配的候选人。一个标记为primary
。除非我通过xml手动指定候选者,否则我希望将主要的候选者连接起来。我最初的方法是使用@Autowired这个属性,但由于这不起作用,我正在寻找替代方案。出于某种原因,我不想使用bean继承。
EDIT2: 如果我交换这两个bean定义,则不会出现问题。该属性自动装配好,直到第一次检测到手动覆盖。这意味着这不是一个意图特征,因为它可能导致奇怪且难以检测某些项目中的错误,其中依赖项未按预期连接。
答案 0 :(得分:1)
如果你看一下AutowiredAnnotationBeanPostProcessor
的javaDocs,就会有一条说明:
“注释注入将在XML注入之前执行;因此 后一种配置将覆盖前者的有线属性 通过两种方法。“
这意味着在xml中使用和设置“testField”的属性值设置bean属性会产生两个新bean,其中一个设置了testField,另一个设置为null。
它是一个或另一个。您既可以使用自动装配类,也可以在xml中手动设置,但不能同时执行这两种操作。我猜测当你删除属性spring时只是将同一个自动装配的bean设置为两个名称。
手动设置同一类的bean后,可以使用@Qualifier("au_test1")
注释将它们注入其他bean
答案 1 :(得分:0)
在我看来,这是我通过jira提交的春天的错误。要解决此问题,必须将注释从setter移动到field。 Setter必须留下来允许手动覆盖酒店。应该将可能的setter逻辑(我知道应该避免这种情况)移到@PostConstruct
。改编自以下原始代码:
import org.springframework.beans.factory.annotation.Value;
import javax.annotation.PostConstruct;
public class AutowireTest {
@Value("default")
public String testField;
@PostConstruct
public void init() {
if (testField == null)
throw new RuntimeException("FAIL");
}
public void setTestField(String testField) {
this.testField = testField;
}
}