简体   繁体   中英

Spring MVC Service Beans loaded twice

I have a problem with my Spring MVC application where my @Service classes are being created twice. I found few threads discussing this issue and most of the time it's related to have the <context:component-scan /> defined both in the Application and also Servlet Context. But in my case I have all the configuration in the Application Context file and the Servlet Context conf file is empty. I'm including the web.xml and the applicationContext.xml files.

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:task="http://www.springframework.org/schema/task"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

    <tx:annotation-driven />        
    <mvc:annotation-driven />
    <task:annotation-driven />
    <context:component-scan base-package="my.app" />
    <mvc:resources mapping="/resources/**" location="/resources/" />
    <mvc:resources mapping="/assets/**" location="/WEB-INF/assets/" />
    <mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"/>

    <bean id="templateResolver"
        class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".html" />
        <property name="characterEncoding" value="UTF-8" />
        <property name="templateMode" value="HTML5" />
        <property name="cacheable" value="false" />
    </bean>
    <bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
        <property name="templateResolver" ref="templateResolver" />
        <property name="additionalDialects">
        <set>
          <bean class="org.thymeleaf.extras.springsecurity3.dialect.SpringSecurityDialect"/>
        </set>
        </property>
    </bean>
    <bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
        <property name="templateEngine" ref="templateEngine" />
        <property name="characterEncoding" value="UTF-8" />
        <property name="order" value="1" />
        <property name="viewNames" value="thymeleaf/*" />
    </bean>

      <mvc:interceptors>
        <!-- Changes the locale when a 'locale' request parameter is sent; e.g. 
        /?locale=de -->
        <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
      </mvc:interceptors>
      <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
        <property name="cookieName" value="myCookie" />
        <property name="defaultLocale" value="sk_SK" />
      </bean>


    <import resource="spring/spring-security.xml"/>     
    <import resource="spring/data-source.xml" />
    <import resource="spring/lang-source.xml"/>
    <import resource="spring/data-properties.xml"/>
    <import resource="spring/data-managers.xml" />
</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <session-config>
        <session-timeout>300</session-timeout>
    </session-config>

    <servlet>
        <servlet-name>appServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>0</load-on-startup>
    </servlet>  

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

    <servlet-mapping>
        <servlet-name>appServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <filter>
        <filter-name>SetCharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <!-- Spring Security -->
    <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>

</web-app>

If you use spring mvc. There will be two context in your application. the spring context which is based on applicationContext.xml and the appServlet-servlet.xml(the name is based on your servlet name appServlet).

When the spring context init, it will component-scan your package defined in applicationContext.xml. It is the first time your service created. Then when you use DispatcherServlet, it will create a spring context. If you have appServlet-servlet.xml, it is based on this. if else, it will component-scan all your classpath. It is the second time your service created.

If you don't want it, you can write it in your applicationContext.xml:

<context:component-scan base-package="my.app">
    <context:exclude-filter type="annotation"expression="org.springframework.stereotype.Controller" />
</context:component-scan>

And then you should create appServlet-servlet.xml and write component-scan like this:

<context:component-scan base-package="my.app" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

So you can hold all your compontent and service in your spring context. And spring mvc will just hold the controller.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM