我有一个使用Sring IoC框架的Web应用程序。
我使用Spring的Java配置,我只使用@Configuration
带注释的模块定义(代码中的其他地方没有DI相关标签)。
Spring注册表是建立在Web应用程序启动的基础上,感谢Spring上下文加载器监听器(有点修改版本),并且web.xml中的 contextConfigLocation 参数配置为指向@Configuration注释类。
一切都很好,我得到一个AnnotationConfigWebApplicationContext。
现在,我想在我的应用程序中安装插件,这些插件将有自己的@Configuration
带注释的配置类,并将使用一些主要的应用程序服务。 但是我不希望修改主应用程序来加载这些新模块。
所以,我认为我可以简单地使用带注释的类的包搜索,但是现在,似乎我可以使用两个具有相同类型的bean,即使它们具有不同的id,并且显然AnnotationConfigWebApplicationContext doc声明:
注意:如果有多个@Configuration类,以后的
@Bean
定义将覆盖先前加载的文件中定义的定义。这可以用来通过额外的Configuration类故意覆盖某些bean定义。
我不希望这样,因为模块应该能够提供替代版本的服务,而不是(alwways)覆盖现有服务 - 特别是如果我想要一个“moduleDef”bean。
我尝试使用不同的方法,但上下文和相关服务的层次结构对我来说很重要。
那么,有人知道我如何达到目标吗?
由于
答案 0 :(得分:3)
你可以拥有多个相同类型的bean,但是你不能拥有2个或更多个相同ID <的bean / strong>在单个Spring ApplicationContext中 - 无论您使用的是XML还是JavaConfig。
重写机制与bean ID相匹配,因此您需要做的就是确保唯一ID,即:coreModuleDef
,someOtherModuleDef
,anotherModuleDef
。我不认为您需要每个模块定义的ID相同吗?什么应该足够的是类型相同,但不是ID。
您还可以通过在allowBeanDefinitionOverriding
上将false
设置为AnnotationConfigWebApplicationContext
来关闭覆盖机制,以便在您意外覆盖bean时获得异常:
public class MyDispatcherServlet extends DispatcherServlet {
@Override
protected void postProcessWebApplicationContext(
ConfigurableWebApplicationContext wac) {
((AnnotationConfigWebApplicationContext) wac)
.setAllowBeanDefinitionOverriding(false);
}
}
或:
public class MyContextLoaderListener extends ContextLoaderListener {
@Override
protected void customizeContext(
ServletContext servletContext,
ConfigurableWebApplicationContext applicationContext) {
((AnnotationConfigWebApplicationContext) wac)
.setAllowBeanDefinitionOverriding(false);
}
}