您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Spring XML文件配置层次结构帮助/说明

Spring XML文件配置层次结构帮助/说明

名为“ applicationContext.xml”的文件没有什么特殊之处,只是它是Spring期望作为其配置文件名称。使用一个名为该文件文件或多个名为“ dog.xml”,“ cat.xml”和“ alien.xml”的文件将完全相同。你遇到的麻烦来自同时使用多个ApplicationContext,而不是来自多个XML文件。我最近回答了一些人的问题,这些人因不了解这些概念而遇到问题。查看这些答案,看看你还有什么问题:

编辑:针对你的新问题:

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

我猜这个“ 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,该文件foo-servlet.xml由从派生的文件配置servlet-name。现在,由于你context:component-scan在其中放置了一个,它将以递归方式扫描给定的包并为所有带注释的类创建bean。你提供给它的包com.myapp看起来像是整个应用程序的基础包,因此Spring将在与DispatcherServlet关联的这一ApplicationContext中,从应用程序中所有带注释的类(包括数据访问类)创建Bean 。通常,此上下文中应只包含直接支持DispatcherServlet的视图层内容和bean,因此这是一种错误的配置。

在我的data.xml文件中,有数据源bean就是这样。没有其他的bean,其他所有东西都自动装配和注释。

大概此“ data.xml”文件就是你在contextConfigLocationcontext-param中列出的文件。假设你还将ContextLoaderListener添加到了中web.xml,例如

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

然后该文件将用于创建第二个ApplicationContext-根上下文。那就是这个听众所做的。请注意,它实际上是根据中列出的所有文件构建上下文的contextConfigLocation,并且如果你还在该列表中包括“ servlet.xml”,那么你已经将该配置加载了两次:在根上下文以及关联的上下文中与DipatcherServlet。希望你现在看到XML配置文件和它们配置的ApplicationContext之间如何进行明显的区分。相同的XML文件可以轻松地用于配置两个不同的上下文。这样做是否正确是另一个问题。在这种情况下,事实并非如此。

我描述这两个上下文的顺序实际上是倒退的。我只是在听你对你所做的事情的描述。作为servletcontextlistener的ContextLoaderListener 将始终在任何Servlet启动之前执行。这意味着首先创建根上下文,然后创建另一个上下文。这是设计使然,以便DispatcherServlet创建其上下文时,可以将该上下文添加为根上下文的子级。我已经在其他文章中描述了这种关系。这最重要的效果是,根上下文中的bean可用于DispatcherServlet的上下文,也可以通过DispatcherServlet的上下文使用。这也适用于自动装配的关系。这很重要,因为仅 DispatcherServlet在其关联上下文中查找所需的bean,例如控制器实例。但是,你的控制器显然必须与支持bean连线。因此,传统上,控制器位于DispatcherServlet的上下文中,而支持bean则位于根上下文中。

然后,我尝试将@Transacational添加到我的服务bean中,它不会持久存在。

为了使@Transactional工作,你必须<tx:annotation-driven/>在带注释的Bean所在的ApplicationContext的配置中包括标记。诀窍是弄清楚“它住的地方”部分。子级中的Bean可以覆盖父级上下文中的Bean。因此-我只是在这里猜测-如果你如上所述将所有bean都加载到DispatcherServlet上下文中,但是将其<tx:annotation-driven/>放在根上下文中,则可能在根上下文中有一个可正确事务处理的bean,但不是之所以使用它,是因为该副本与父/子层次结构中的servlet“更近”,并且它所在的上下文没有得到<tx:annotation-driven/>配置。

当我将servlet的context:component-scan标记更改为指向com.myapp.web,然后将一个context:component-scan标记添加到data.xml文件时,一切正常。

它仍然在一定程度上取决于你在哪个ApplicationContexts中包括哪些配置文件,但是至少可以说,通过这样做,你从DispatcherServlet的上下文中删除了很多导致问题的bean。特别是,在根上下文中正确配置的@Transactional Bean将不再在子上下文中被Bean遮蔽,并且将被注入到控制器中,因此你的持久性工作将可以正常工作。

所以…最主要的是,你有两个相关的ApplicationContext。你必须保持对这一事实的了解,并控制在哪种上下文中使用哪种bean。

Java 2022/1/1 18:21:56 有472人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶