在我们的软件中,我们使用的是spring java config。我们有一个设置,其中一个配置扩展了抽象配置。请看一下这个测试用例:
import java.util.concurrent.atomic.AtomicInteger; import org.junit.Test; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; public class SpringConfigTest { @Test public void test() { final AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MyConfig.class); ctx.getBeansOfType(AtomicInteger.class).entrySet().stream().forEach( b -> System.out.println(b.getKey() + " : " + b.getValue() + " (" + b.getValue().hashCode() + ")")); } @Configuration public static class MyConfig extends AbstractConfig { @Bean(name = "anotherName") public AtomicInteger myBean() { return new AtomicInteger(5); } } public static abstract class AbstractConfig { @Bean public AtomicInteger myBean() { return new AtomicInteger(10); } } }
我的想法是,MyConfig
覆盖AbstractConfig
,并且在创建的ApplicationContext中,名称AtomicInteger
下只有一个anotherName
类型的bean。
结果是:
anotherName : 5 (2109798150) myBean : 5 (1074389766)
所以它说,有两个bean(两个实例 - 每个名称一个) - 甚至更多的是:使用相同的方法(MyConfig#myBean()
)来创建它们。
这种行为对我们来说很奇怪:我们期望spring要么尊重通常的java继承方式,要么只创建来自MyConfig
的bean ...或者至少会创建两个独立的bean(“10”和“5”)以防AbstractConfig
为独立配置。
在调查此问题时,我们还尝试在MyConfig
类上注册方法名称:
public static class MyConfig extends AbstractConfig { @Bean(name = ["anotherName", "myBean"]) public AtomicInteger myBean() { ...
这次我们只得到一个豆子:
anotherName : 5 (2109798150)
..对我们来说更令人惊讶的是。
有人知道这是否真的是正确的行为,还是我们只是错误地使用它?我们应该在春天的jira上提票吗? 提前谢谢!
答案 0 :(得分:1)
我不是春天职业选手,但我说这种行为是设计的。为了实现你想要的东西(我希望我猜对了)"注入这个豆而不是其他的#34;您可以在bean上使用@Primary,根据您使用@Conditional的情况选择性地启用配置,即@Profile。
答案 1 :(得分:0)
在Spring中,可以先按类型接线bean,然后按名称接线。 因此,@Qualifier(“ myBeanName”)可以消除自动装配多个具有相同类型的Bean的歧义,例如
所以: 非抽象Bean被赋予另一个名称这一事实使它在应用程序上下文中被视为另一个Bean。
您可以在非配置类中声明bean。这称为“精简”模式,但在应用程序上下文中它仍然是bean。 另请参见精简模式下的this答案。
我不知道一个bean可以给多个名字,但是由于默认情况下Spring bean是单例,因此在第二种情况下只能创建一个bean,因为“ myBean”已经存在并且只有一个具有该名称的bean可以在应用程序上下文中。