Spring XML文件配置层次结构帮助/解释

8 浏览
0 Comments

Spring XML文件配置层次结构帮助/解释

当我刚开始学习Spring时,配置都是在applicationContext.xml文件中进行的。然后当我开始阅读关于较新版本Spring的书籍时,他们都把配置放在独立的XML文件中,如myapp-servlet-xml、myapp-security.xml、myapp-service.xml等,通过在web.xml文件中配置contextConfigLocation来指定。所以,例如,我一直在跟随的代码中,contextConfigLocation是这样设置的:\n


    contextConfigLocation
    
        /WEB-INF/myapp-servlet.xml
        /WEB-INF/myapp-data.xml
    

\n无论如何,最近我遇到了一个配置问题(StackOverflow上的热心人帮助我解决了),这是由于这种分离导致的。这些书中的示例没有applicationContext.xml文件,后来当我尝试向应用程序中添加自动扫描和注解时,就会出现问题。我尝试将所有内容都移动到applicationContext.xml中,并放弃其他文件,问题就解决了。除此之外,没有其他变化,我只是把所有内容放到了applicationContext.xml中。\n所以,这个问题以及其他人的评论让我有点理解,即使你不创建applicationContext.xml,它仍然会被使用,并且它是某种配置层次结构的顶层。我希望有人能向我解释这一切是如何工作的,因为我在任何地方都没有找到解释。\n例如,如果我将某些context:component-scan标签放在低于applicationContext.xml的配置文件中,可能会导致某些类无法被扫描到。我不理解优先级和必须放在哪里才能确保在整个应用程序中可见等问题。如果有人能清楚地解释或指导我去了解这个问题,我将非常感激,谢谢。希望我的问题有意义。

0
0 Comments

Spring XML文件配置层次结构帮助/解释

在Spring中,名为"applicationContext.xml"的文件并没有什么特别之处,除了它是Spring默认配置文件的名称。使用一个名为"applicationContext.xml"的文件或者使用多个名为"dog.xml"、"cat.xml"和"alien.xml"的文件都会以相同的方式工作。你遇到的问题并不是因为有多个XML文件,而是因为同时使用了多个ApplicationContext。最近,我回答了几个关于这些概念的问题。请查看这些答案,看看你还有哪些问题:

- "声明Spring Bean在父上下文和子上下文中的区别"(链接:Declaring Spring Bean in Parent Context vs Child Context

- "Spring-MVC: 什么是'context'和'namespace'?"(链接:Spring-MVC: What are a "context" and "namespace"?

编辑:针对你的新问题:

我的servlet.xml文件中有一个<context:component-scan base-package="com.myapp"/>标签。

我猜测这个"servlet.xml"文件的名称类似于foo-servlet.xml,其中在你的web.xml中配置的DispatcherServlet的名称为"foo",如下所示:

<servlet>
    <servlet-name>foo</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

按照惯例,当这个DispatcherServlet启动时,它将创建一个新的ApplicationContext,该ApplicationContext由文件foo-servlet.xml配置,该文件是根据派生的。现在,由于你在其中放置了一个,它将递归扫描给定的包并为所有带注解的类创建bean。你给它的包名com.myapp看起来是你整个应用程序的基本包,所以Spring将在与DispatcherServlet关联的这个ApplicationContext中创建来自应用程序中所有带注解的类的bean,包括数据访问类。通常,这个上下文应该只包含视图层的内容和直接支持DispatcherServlet的bean,所以这是一种错误的配置。

在我的data.xml文件中,我只有数据源bean,其他都是自动装配和注解。

假设这个"data.xml"文件是你在上列出的文件。假设你还在中添加了ContextLoaderListener,如下所示:

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

那么这个文件将用于创建第二个ApplicationContext,即根上下文。这就是这个监听器的作用。请注意,它实际上是根据中列出的所有文件构建上下文,如果你还在列表中包含了"servlet.xml",那么你就加载了两次该配置文件:一次是在根上下文中,一次是在与DispatcherServlet相关联的上下文中。希望你现在能看到XML配置文件和它们配置的ApplicationContext之间的明显区别。同一个XML文件可以很容易地用于配置两个不同的上下文。是否这样做是正确的另一个问题。在这种情况下,是不正确的。

我描述这两个上下文的顺序实际上是相反的。我只是按照你描述的步骤进行的。ContextLoaderListener作为一个ServletContextListener,将在任何servlet启动之前执行。这意味着根上下文首先创建,然后是其他上下文。这是有意设计的,因此当DispatcherServlet创建它的上下文时,它可以将该上下文作为根上下文的子上下文添加。我在之前的帖子中描述了这种关系。最重要的效果是,根上下文中的bean对DispatcherServlet的上下文可用。这也适用于自动装配的关系。这很重要,因为DispatcherServlet只在与它关联的上下文中查找它需要的bean,如控制器实例。然而,显然,你的控制器必须与支持它们的bean进行关联。因此,传统上,控制器位于DispatcherServlet的上下文中,而支持的bean位于根上下文中。

然后我尝试为我的service bean添加,但它无法持久化。

为了使起作用,你必须在带注解的bean所在的ApplicationContext的配置中包含该标签。关键是弄清楚"它在哪里"的部分。子上下文中的bean可以覆盖父上下文中的bean。因此,我只是猜测,如果你像我上面描述的那样将所有的bean加载到DispatcherServlet的上下文中,但是将放在根上下文中,可能会在根上下文中有一个正确配置的bean,但它却没有被使用,因为重复的bean在父/子层级中更接近servlet,而且它所在的上下文没有得到的配置。

当我将servlet的context:component-scan标签改为指向com.myapp.web,并在data.xml文件中添加了context:component-scan标签后,一切都正常了。

这仍然在某种程度上取决于你将哪些配置文件包含在哪些ApplicationContext中,但至少我可以说,通过这样做,你从DispatcherServlet的上下文中删除了许多导致问题的bean。特别是,在根上下文中正确配置的bean将不再被子上下文中的bean遮盖,并将被注入到你的控制器中,所以你的持久化工作就会正常工作了。

所以...最重要的是要知道你有两个相关的ApplicationContext。你必须意识到这个事实,并控制哪些bean放在哪个上下文中。

这样是否包含了所有内容呢?

非常感谢你的帮助和链接。链接为我提供了我所寻找的一些澄清。不过,我还有一个问题。我在我的servlet.xml中有一个标签。在我的data.xml文件中,我只有数据源bean,其他都是自动装配和注解。然后我尝试为我的service bean添加,但它无法持久化。当我将servlet的context:component-scan标签改为指向com.myapp.web,并在data.xml文件中添加了context:component-scan标签后,一切都正常了。

因此,我的问题是,你能澄清一下这是为什么吗?我有一个dispatcher servlet,它查看servlet.xml,所以它不是根上下文。嗯...我猜我仍然不完全理解事物是如何结合在一起的。非常感谢你的帮助。

非常感谢!我觉得你真的帮助我澄清了我通过阅读书籍和Spring文档所无法理解的东西。我确实将我的servlet.xml文件放入了contextConfigLocation列表中,正如你所说,这导致了两个上下文。这可能不是我的唯一问题,但肯定是其中之一。现在有了你的解释,我应该能够仔细检查并确保一切都配置正确。还要感谢你列出Spring如何加载文件。我确实觉得一切更加清晰了。再次感谢。

这是一个很好的解释。非常感谢。在我的情况下,我使用了上下文的include和exclude过滤器来控制这一点,效果非常好!

0