6

アプリケーションを Spring Integration と統合しようとしていますが、カスタム Spring Bean が 2 回初期化されていることを経験しています。基本的に、これらの Bean の init メソッドが 2 回呼び出されていることがわかります。1 回目はサーバーの起動時、2 回目は 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 リクエストの作成中に、2 回呼び出されます。

    <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 定義ファイルへのインポートと、このファイルの component-scan および annotation-config を削除しました。

<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 つのコンテキストがあります。サーブレット コンテキストとルート コンテキスト。

一般に、「Web」Bean (@Controller、ビュー、Http インバウンドアダプターなど) をサーブレットコンテキストに配置し、すべての「ビジネス」Bean をルートコンテキストに配置することをお勧めします。

Bean をインポートする代わりに、コンテキスト ローダー リスナーを使用してルート コンテキストに配置する必要があります。

サーブレット コンテキストの Bean は、ルート コンテキストの Bean への参照を取得できますが、その逆はできません。

ルート コンテキストが最初に読み込まれます。ファイル名は重要ではありませんが、ワイルドカードを使用するcontextConfigLocation場合は、サーブレット コンテキストの構成が再度取得されないように注意する必要があります。

于 2013-08-16T13:19:02.440 に答える