2013-08-16 97 views
4

我正在嘗試將我的應用程序與Spring Integration集成,並且遇到我的自定義spring bean正在初始化兩次,基本上我看到這些bean的init方法被調用兩次,一次在服務器啓動期間和第二次通過DispatcherServlet進行HTTP請求時。Spring bean初始化兩次 - Spring Integration

這裏是我的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> 

包含所有自定義文件springbeans-config.xml中如上所示導入bean定義。 例如在服務器啓動時以及在通過DispatcherServlet調用HTTP請求時,下面的bean定義將被調用兩次。

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

想知道我在這裏錯過了什麼。將不勝感激任何指針/幫助。謝謝。

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

更新 - 解決

SpringIntegration樣本內高利貸例如幫助解決這個問題。

這裏是更新的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> 
+0

您正在用XML定義您的bean,但我注意到您還在使用'component-scan'掃描bean - 您的類是否有任何註釋? – MattR

+0

是的,他們這樣做。我只是在這裏添加一個bean作爲例子。在service-activator組件中還有其他helper bean自動裝配,並在springbeans-config.xml下提供。 – codehammer

+0

所以要清楚的是,你是否使用類似@ @ Component'的_and_在XML中定義的東西來註釋bean?您能否爲正在初始化兩次的單個類顯示完整示例? – MattR

回答

5

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

將servlet上下文中的「web」bean(@Controllers,views,Http入站adatpers等)和根上下文中的所有「business」bean放在一起是很好的做法。

您應該使用上下文加載器偵聽器將它們放入根上下文中,而不是導入您的bean。

servlet上下文中的Bean可以在根上下文中獲得對Bean的引用,但反之亦然。

首先加載根環境;文件名並不重要,但在contextConfigLocation中使用通配符時,需要小心不要再次拾取servlet上下文配置。

+0

感謝您的見解。那麼,上面的「更新」配置看起來不錯嗎? 基本上,servlet-config.xml包含所有Spring集成組件,例如http入站網關,鏈路,路由器,過濾器,服務激活器等。 服務激活器所需的所有幫助器bean都位於springbeans-config.xml 。 servlet-config.xml和springbeans-config.xml都是相互獨立的,因爲它們不會以任何方式導入對方。 – codehammer

+2

嗯,它們並不真正獨立 - 根上下文是servlet上下文的父代(允許你從服務激活器引用bean),但是是正確的;沒有進口。這是個人喜好;讓servlet上下文中的所有SI組件成爲一個很好的圖形(如果使用SI集成圖形查看器)。有些人只把http入站適配器放在servlet上下文中,而其他的流(從第一個通道開始)放在根上下文中。 –

+0

當然,我只是從配置的角度來看,沒有具體的進口。我在Servlet上下文中擁有所有SI組件的唯一問題是這些幫助器bean會在服務器啓動期間第二次初始化兩次,並且在實際HTTP請求期間第二次初始化。因此,在springbeans中有這些bean(由服務激活器引用)在根環境下加載的config.xml有幫助。 Ur last語句是一個很好的觀點,並且允許我認爲甚至servlet-config中的SI鏈可以在springbeans-config中移動,這樣它們就不會在每個HTTP請求中被初始化。正確? – codehammer