2012-08-15 126 views
3

我使用autowire @Controller創建了一個名爲RegistrationController的彈簧控制器。我有我自己的好奇心的緣故創建一個默認的構造函數如下,並增加了記錄聲明:正在創建Spring多個bean實例

public RegistrationController() { 
    logger.info("Registration Controller (Constructor) called-->"+this); 
} 

我發現,當我在春源IDE(V2.9)在開始我的Tomcat服務器(第7版)日誌文件我看到以下內容:

INFO: Initializing Spring root WebApplicationContext 
2012-08-15 15:12:28,808 [pool-2-thread-1] INFO com.controllers.registration.RegistrationController - Registration Controller (Constructor) called-->[email protected] 
Aug 15, 2012 3:12:28 PM org.apache.catalina.core.ApplicationContext log 
INFO: Initializing Spring FrameworkServlet 'main' 
2012-08-15 15:12:29,256 [pool-2-thread-1] INFO com.controllers.registration.RegistrationController - Registration Controller (Constructor) called-->[email protected] 

據我所知,在默認情況下這個RegistrationController應該是單獨的對象,必須進行創建只有一個實例。但是,正如您從日誌文件中看到的那樣創建了兩個實例。不知何故,我覺得這是不正確的。但我沒有確切的答案。

一些從我的web.xml中的重要線路如下:

<?xml version="1.0" encoding="UTF-8"?> 
<web-app id="WebApp_ID" version="2.4" 
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> 
<context-param> 
    <param-name>contextConfigLocation</param-name> 
    <param-value>/WEB-INF/classes/applicationContext*.xml</param-value> 
</context-param> 
. 
. 
<servlet> 
    <servlet-name>main</servlet-name> 
    <servlet-class> 
     org.springframework.web.servlet.DispatcherServlet 
    </servlet-class> 
    <load-on-startup>2</load-on-startup> 
</servlet> 



<servlet-mapping> 
    <servlet-name>main</servlet-name> 
    <url-pattern>*.htm</url-pattern> 
</servlet-mapping> 
<servlet-mapping> 
    <servlet-name>main</servlet-name> 
    <url-pattern>*.jspx</url-pattern> 
</servlet-mapping> 
<servlet-mapping> 
    <servlet-name>main</servlet-name> 
    <url-pattern>*.do</url-pattern> 
</servlet-mapping> 
    . 
    . 
    </web-app> 

您一定已經猜到了,我有一個主servlet.xml中和的applicationContext.xml作爲我的Spring配置文件。

你能幫我理解這裏發生了什麼嗎?

EDITED因爲我不能回答我的問題之前8個小時已經過去了:

感謝@Andna您的建議,以尋找在applicationContext.xml中和主servlet.xml中<context:component-scan />。我在這兩個文件中都有這個元素,因此每個春天的bean都被掃描了兩次。

但是,從applicationContext.xml中刪除<context:component-scan />導致我的Spring安全配置中斷。爲了更詳細地走我曾創造了實現org.springframework.security.core.userdetails.UserDetailsService

@Service("userDetailsService") 
public class DuncanUserDetailsServiceImpl implements UserDetailsService { 
@Override 
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException { 
} 
} 

爲了支持這一類我曾在我的applicationContext-security.xml文件以下(縮短的版本)文件類:

<beans:beans xmlns="http://www.springframework.org/schema/security" 
xmlns:beans="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:context="http://www.springframework.org/schema/context" 
xsi:schemaLocation=" 
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd 
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> 

<beans:bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"> 
     <beans:property name="userDetailsService" ref="userDetailsService"/> 
</beans:bean> 

<beans:bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager"> 
    <beans:property name="providers"> 
     <beans:list> 
      <beans:ref local="daoAuthenticationProvider" /> 
     </beans:list> 
    </beans:property> 
</beans:bean> 

<authentication-manager> 
    <authentication-provider user-service-ref="userDetailsService"> 
     <password-encoder ref= "passwordEncoder"> 
      <salt-source user-property="userName"/> 
     </password-encoder> 
    </authentication-provider> 
</authentication-manager> 

<beans:bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" /> 

</beans:beans> 

因此消除來自applicationContext.xml的<context: component-scan />導致「userDetailsS​​ervice」對象實例丟失,並且我的日誌文件中出現大量錯誤。

所以我所做的就是我一直在我的組件掃描在主servlet.xml中,因爲它是:

<context:component-scan base-package="com.some.org" > 
     <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> 
    </context:component-scan> 

但是,我用在applicationContext.xml排除篩選如下編輯組件掃描:

<context:component-scan base-package="com.bankofamerica" > 
     <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> 
     <context:exclude-filter type="regex" expression="com.some.org.common.http.HTTPClient" /> 
    </context:component-scan> 

這幫助我實現這兩個事情:

  1. 在確認單objec t確實是單身人士
  2. 確保Spring安全性與以前一樣工作。

謝謝大家的所有精彩建議。

+6

applicationContext.xml和main-servlet.xml的內容? – bluesman 2012-08-15 19:40:23

+0

我認爲8小時已經過去了很長時間,您可以編輯問題的答案並將其添加爲真正的答案。 – 2014-02-07 13:52:10

回答

4

也許你在applicationContext.xmlmain-servlet.xml中都有組件掃描兩次,所以Spring會掃描註釋類兩次?

+0

是的安娜,你是絕對正確的!但是,如果我從applicationContext.xml中刪除,那麼我對Spring安全配置有問題。 – Raj 2012-08-15 19:54:03

+0

將您的spring安全配置導入到applicationContext.xml中,並刪除main-servlet.xml中的一個。 – rptmat57 2012-08-15 20:09:33

+0

@ rptmat57請看我的回答。 – Raj 2012-08-15 20:14:53

1

我結束了下面的配置,的src /主/ web應用/ WEB-INF/web.xml文件:

<web-app xmlns=... version="2.4"> 
    <servlet> 
     <servlet-name>dispatcher</servlet-name> 
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> 
     <load-on-startup>2</load-on-startup> 
    </servlet> 

    <servlet-mapping> 
     <servlet-name>dispatcher</servlet-name> 
     <url-pattern>/</url-pattern> 
    </servlet-mapping> 

    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 
    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value>/WEB-INF/application-context.xml,/WEB-INF/security.xml,/WEB-INF/db.xml,/WEB-INF/services.xml</param-value> 
    </context-param> 

    <filter> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

    <filter> 
     <filter-name>sitemesh</filter-name> 
     <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>sitemesh</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

</web-app> 

我覺得跟春天最常見的問題是Spring上下文的誤解。仔細看看DispatcherServlet。 Spring將自動搜索dispatcher-servlet.xml,它是Web上下文。來自此背景的豆類不可用於在根環境中定義的豆類,例如,在contextConfigLocation參數中指定。爲了使其可用,人們通常在contextConfigLocation中包含dispatcher-servlet.xml,這在邏輯上會導致Spring初始化Web上下文兩次。那麼配置spring-security(全局方法安全)或組件掃描或sitemesh將會是一場噩夢,配置將會「不穩定」。