有一个完全基于注释的spring项目A。 我需要在项目B中有条件地覆盖一些bean,该项目B是使用Spring 4.1.3的旧应用程序,并使用基于xml的配置。
有FooConfig使用@ComponentScan配置bean。此配置是我的第三方代码。即我无权访问
@ComponentScan(basePackages = {"com.foo.bean"})
@Configuration
public class FooConfig {
}
我在末端创建了一个BarConfig,它导入了FooConfig并根据条件覆盖了一些bean。这是使用@Conditional
实现的@Configuration
@Import(FooConfig.class)
public class BarConfig {
@Bean(name="helloService")
@Conditional(IsSpanishCondition.class)
public HelloService getHelloService() {
return new HelloService() {
@Override
public String getGreeting(String name) {
return "Hola "+name;
}
};
}
}
我在我的application-context.xml中包含了BarConfig
<context:annotation-config/>
<bean class="com.foo.config.BarConfig"/>
虽然此方法在Spring 5.1.2.RELEASE中完美无缺,但在Spring 4.1.3.RELEASE中不起作用
00:14:20.617 [main]信息org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader-跳过[BeanMethod:name = getHelloService,declaringClass = com.foo.config.BarConfig]的bean定义:bean'helloService的定义' 已经存在。此顶级bean定义被视为替代。
此外,在完全基于注释的上下文中,我在Spring 4中也观察到了同样的问题。即不是由于xml和注释配置的混合,而是由于此处使用的Spring版本
问题
春季5发生了什么变化?
在使用同时使用xml和注释配置的Spring应用程序时,有什么经验法则吗?特别是在覆盖bean时?
也是FTR,这些都是可行的解决方案
1.使用BeanPostProcessor覆盖Bean
2.使用配置文件。但这不适用于复杂的条件。
@Profile("ENGLISH")
@Configuration
@Import(FooConfig.class)
public class EnglishConfig {
}
@Profile("SPANISH")
@Configuration
public class SpanishConfig {
@Bean(name="helloService")
public HelloService getHelloService() {
return new HelloService() {
@Override
public String getGreeting(String name) {
return "Hola "+name;
}
};
}
}
答案 0 :(得分:0)
这里的问题是,您正在尝试从@Configuration类覆盖xml bean,现在我不是100%确信,但是在春季4中,xml bean在选择bean上仍然具有优先权,因此@Configuration bean将不会获得覆盖xml bean的权限。该问题已在春季5解决。
您猜想您使用BeanPostProcessor的方法是唯一可行的解决方案。
我在想,也许您可以使用其他bean名称,实现自己的行为,并使用@Qualifier注释选择将被选中的bean?