Spring:AnnotationConfigWebApplicationContext如何覆盖以后的bean?

时间:2011-06-08 09:14:10

标签: spring annotations external

我有一个使用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。

我尝试使用不同的方法,但上下文和相关服务的层次结构对我来说很重要。

那么,有人知道我如何达到目标吗?

由于

1 个答案:

答案 0 :(得分:3)

可以拥有多个相同类型的bean,但是你不能拥有2个或更多个相同ID <的bean / strong>在单个Spring ApplicationContext中 - 无论您使用的是XML还是JavaConfig。

重写机制与bean ID相匹配,因此您需要做的就是确保唯一ID,即:coreModuleDefsomeOtherModuleDefanotherModuleDef。我不认为您需要每个模块定义的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);
    }
}