Подтвердить что ты не робот

@Service построены дважды

У меня проблема с моим приложением Spring, где мои классы @Service создаются дважды при запуске приложения. Я знаю, что это проблема с моей конфигурацией, как я это пережил раньше, но что именно я делаю неправильно?

Есть ли что-то принципиально неправильное в том, как я описал свою конфигурацию ниже? (Я опустил все, что считаю неуместным)

web.xml:

<servlet>
    <servlet-name>myapp</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>myapp</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/myapp-config.xml
        /WEB-INF/myapp-security.xml
        /WEB-INF/myapp-mvc.xml
    </param-value>
</context-param>

<listener>
    <listener-class>com.myapp.servlet.MyAppContextListener</listener-class>
</listener>

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

MyApp-servlet.xml

<context:component-scan base-package="com.myapp" annotation-config="true" />
<mvc:annotation-driven />

MyApp-config.xml

<context:component-scan base-package="com.myapp" annotation-config="true" />
<context:annotation-config />
4b9b3361

Ответ 1

В дополнение к @GaryF answer для этой проблемы существует следующее красивое решение (используется в проектах, сгенерированных Spring Roo):

MyApp-config.xml

<!-- Load everything except @Controllers -->
<context:component-scan base-package="com.myapp">
    <context:exclude-filter expression="org.springframework.stereotype.Controller"
        type="annotation"/>
</context:component-scan>

MyApp-servlet.xml

<!-- Load @Controllers only -->
<context:component-scan base-package="com.myapp" use-default-filters="false">
    <context:include-filter expression="org.springframework.stereotype.Controller" 
        type="annotation"/>
</context:component-scan>

EDIT:

Удаление <context:component-scan> из myapp-config.xml означает, что все ваши автообнаруженные аннотированные beans зарегистрированы в контексте DispatcherServlet (то есть, контекст загружен из myapp-servlet.xml).

Однако рекомендуемый подход заключается в использовании контекста сервлета для специфичных для представления вещей (таких как контроллеры) и использования корневого контекста (myapp-config.xml) для основных служб вашего приложения. Решение выше упрощает этот подход.

Что касается практических соображений, когда ваши основные службы размещены в контексте сервлет-приложений, к ним нельзя получить доступ из-за пределов этого сервлета, например, из других сервлетов (вам может потребоваться использовать другие сервлеты для реализации другого технологии доступа) или фильтры (например, фильтры Spring Security). Это причина наличия основных сервисов в контексте корневого приложения.

Ответ 2

В качестве дополнения к ответу @axtavt, Id хотел бы предоставить соответствующий Spring JavaConfig здесь.

В RootConfig.java:

@ComponentScan(basePackages = { "com.myapp" },
    excludeFilters = @Filter({Controller.class, Configuration.class}))

В WebMvcConfig.java:

@ComponentScan(basePackages = { "com.myapp" },
    useDefaultFilters = false, includeFilters = @Filter(Controller.class))

Ответ 3

Вы выполняете два отдельных компонентных сканирования по одному базовому пакету. Удалите один из них.