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

car*_*ian 41 spring

当我第一次开始学习Spring时,在applicationContext.xml文件中配置了一些东西.然后当我开始专门阅读更新版本的spring时,他们都在单独的XML文件中完成了配置,例如myapp-servlet-xml,myapp-security.xml,myapp-service.xml等.在web.xml文件中配置contextConfigLocation.因此,例如,我一直关注的代码就是它的contextConfigLocation:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/myapp-servlet.xml
        /WEB-INF/myapp-data.xml
    </param-value>
</context-param>
Run Code Online (Sandbox Code Playgroud)

无论如何,最近我遇到了一个配置问题(StackOverflow的帮助人员帮助我弄清楚),这是由于这种分离.这些书中的示例没有applicationContext.xml文件,稍后当我尝试向应用程序添加自动扫描和注释时,这会导致问题.我尝试将所有内容移动到applicationContext.xml中并取消其他文件并解决了问题.没有其他改变,我只是将所有内容都放在applicationContext.xml中.

因此,这与其他人的评论一起使我有理解,即使您没有创建applicationContext.xml,它仍然被使用,并且它是某种配置层次结构的顶级.我希望其他人可以向我解释这一切是如何运作的,因为我没有在任何地方遇到任何解释.

因此,例如,如果我将某些上下文:组件扫描标记放入applicationContext.xml下面的配置文件中,则可能导致某些类无法扫描.那种性质的东西.我不明白优先级和必须去哪里确定应用程序的广泛性等等.如果有人能够清楚地解释它或指向我解释它的资源我会非常感激,谢谢.希望我所要求的是有道理的.

Rya*_*art 87

名为"applicationContext.xml"的文件没有什么特别之处,只不过它是Spring希望作为其默认配置文件的名称.使用一个名为"dog.xml"的文件或多个文件,"cat.xml"和"alien.xml"将以完全相同的方式工作.您遇到的麻烦来自于同时使用多个ApplicationContexts,而不是拥有多个XML文件.我最近回答了一些由于不了解这些概念而导致问题的人提出的问题.看看这些答案,看看你还有什么问题:

在父上下文和子上下文中声明Spring Bean

Spring-MVC:什么是"上下文"和"命名空间"?

编辑:回答您的新问题:

<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>
Run Code Online (Sandbox Code Playgroud)

按照惯例,当此DispatcherServlet启动时,它将创建一个由该文件配置的新ApplicationContext,该文件foo-servlet.xml派生自servlet-name.现在,既然你放了一个context:component-scan,就会递归扫描给定的包并为所有带注释的类创建bean.你给它的软件包com.myapp看起来像是整个应用程序的基础软件包,所以Spring会在你的应用程序中的所有带注释的类中创建bean ,包括数据访问类,在这个与DispatcherServlet相关联的ApplicationContext中.通常,此上下文应该只有视图层内容和bean直接支持其中的DispatcherServlet,因此这是一个错误配置.

在我的data.xml文件中,我有数据源bean,就是这样.没有其他豆类,其他一切都是自动装配和注释.

据推测,这个"data.xml"文件是您在contextConfigLocationcontext-param中列出的文件.假设您还将ContextLoaderListener添加到您的中web.xml,例如

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Run Code Online (Sandbox Code Playgroud)

然后该文件将用于创建第二个ApplicationContext - 根上下文.这就是听众的作用.请注意,它实际上是从列出的所有文件构建上下文contextConfigLocation,如果您还在该列表中包含了"servlet.xml",那么您已经加载了该配置两次:这里在根上下文中以及相关的上下文中使用DipatcherServlet.希望您现在可以看到XML配置文件与它们配置的ApplicationContexts之间的区别.可以轻松使用相同的XML文件来配置两个不同的上下文.这样做是否正确是另一个问题.在这种特殊情况下,事实并非如此.

我在这两个背景中描述的顺序实际上是向后的.我只是按照你对你所做的描述.作为ServletContextListener的ContextLoaderListener 将始终在任何servlet启动之前执行.这意味着首先创建根上下文,然后创建另一个上下文.这是设计使得当DispatcherServlet创建其上下文时,它可以将该上下文添加为根上下文的子项.我在其他帖子中描述了这种关系.这样做的最重要的影响是根上下文中的bean可以通过DispatcherServlet的上下文使用.这也适用于自动连接关系.这很重要,因为DispatcherServlet 在其关联的上下文中查找它需要的bean,比如控制器实例.但是,您的控制器显然必须与支持bean连接.因此,传统上,控制器存在于DispatcherServlet的上下文中,支持bean存在于根上下文中.

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

为了使@Transactional可以工作,您必须<tx:annotation-driven/>在带注释的bean所在的ApplicationContext的配置中包含该标记.诀窍是找出"它住在哪里"的一部分.子进程中的Bean可以覆盖父上下文中的bean.所以-我只是猜测这里-如果你加载所有的豆子放进DispatcherServlet的背景下,我上面描述,但把<tx:annotation-driven/>根背景下,你可能在根上下文这是正确的事务豆,但它不是正在使用一个,因为副本"更接近"父/子层次结构中的servlet,并且它所处的上下文没有得到<tx:annotation-driven/>配置.

当我更改servlet上下文:component-scan标记而不是指向com.myapp.web然后将上下文:component-scan标记添加到data.xml文件时,一切正常.

它仍然在某种程度上取决于您在哪个ApplicationContexts中包含哪些配置文件,但至少我可以说通过这样做,您从DispatcherServlet的上下文中删除了很多bean,这些bean导致了问题.特别是,在根上下文中正确配置的@Transactional bean将不再被子上下文中的bean隐藏,并且会被注入到控制器中,因此您的持久性内容将起作用.

所以......最重要的是你有两个相关的ApplicationContexts.你必须意识到这一事实,并控制哪些bean进入哪种环境.

这涵盖了一切吗?