6

我正在尝试将我的应用程序与 Spring Integration 集成并体验到我的自定义 spring bean 被初始化了两次,基本上我看到这些 bean 上的 init 方法被调用了两次,一次是在服务器启动期间,第二次是在 HTTP 请求时通过 DispatcherServlet 制作。

这是我的 web.xml 配置:

  <servlet>
        <servlet-name>webapp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/servlet-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>webapp</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

这是我的 servlet-config.xml(删除了命名空间)

<import resource="springbeans-config.xml"/>

<context:component-scan base-package="com.test"/>

<context:annotation-config/>

<int:channel id="inboundChannel"/>
<int:channel id="outboundChannel"/>

<http:inbound-gateway request-channel="inboundChannel" reply-channel="outboundChannel" name="/*" supported-methods="GET, POST, PUT, DELETE" reply-timeout="120000"/>

<int:chain input-channel="inboundChannel">
    <int:service-activator ref="clearContext"/>
    <int:service-activator ref="gatewayFilter"/>
    <int:service-activator ref="audit_logger"/>
    <int:service-activator ref="gatewayContextHandler" method="process"/>
</int:chain>

如上所示,导入包含所有 bean 定义的自定义文件 springbeans-config.xml。例如,下面的 bean 定义将被调用两次,在服务器启动期间和发出通过 DispatcherServlet 调用的 HTTP 请求时。

    <bean name="sample" class="com.test.SampleImpl" init-method="init">
    <property name="xpathHelper" ref="XPathHelper"/>
    <property name="cacheManager" ref="cacheManager"/>
</bean>

想知道我在这里缺少什么。将不胜感激任何指针/帮助。谢谢。

==================================================== ==============

更新 - 已解决

SpringIntegration 示例中的loanshark 示例有助于解决此问题。

这是更新的 web.xml

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>

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

<servlet>
    <servlet-name>gateway</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/servlet-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>gateway</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

更新了 servlet-config.xml(删除了命名空间)。删除了此文件中对 bean 定义文件和组件扫描和注释配置的导入。

<http:inbound-gateway request-channel="inboundChannel" reply-channel="outboundChannel" name="/*" supported-methods="GET, POST, PUT, DELETE" reply-timeout="120000"/>

<int:chain input-channel="inboundChannel">
    <int:service-activator ref="clearContext"/>
    <int:service-activator ref="gatewayFilter"/>
    <int:service-activator ref="audit_logger"/>
    <int:service-activator ref="gatewayContextHandler" method="process"/>
</int:chain>

根据示例将 springbeans-config.xml 重命名为 applicationContext.xml,但我想应该没关系。请注意,此文件中也没有导入。

<context:component-scan base-package="com.test"/>

<context:annotation-config/>

<bean name="sample" class="com.test.SampleImpl" init-method="init">
    <property name="xpathHelper" ref="XPathHelper"/>
    <property name="cacheManager" ref="cacheManager"/>
</bean>
4

1 回答 1

5

Spring MVC 应用程序通常有 2 个上下文;servlet 上下文和根上下文。

将您的“web”bean(@Controllers、视图、Http 入站 adatpers 等)放在 servlet 上下文中并将所有“业务”bean 放在根上下文中通常是一种很好的做法。

您应该使用上下文加载器侦听器将它们放在根上下文中,而不是导入您的 bean。

servlet 上下文中的 bean 可以获取对根上下文中 bean 的引用,但反之则不行。

首先加载根上下文;文件名无关紧要,但在使用通配符时,contextConfigLocation您需要小心不要再次拾取 servlet 上下文配置。

于 2013-08-16T13:19:02.440 回答