@ Сервисы построены дважды - PullRequest
28 голосов
/ 02 декабря 2010

У меня проблема с моим приложением 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 />

Ответы [ 3 ]

34 голосов
/ 02 декабря 2010

В дополнение к ответу @ GaryF , существует следующее прекрасное решение этой проблемы (используется в проектах, генерируемых 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 означает, что все ваши автоматически обнаруженные аннотированные bean-компоненты зарегистрированы в контексте DispatcherServlet (то есть в контексте, загруженном из myapp-servlet.xml).

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

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

15 голосов
/ 05 июня 2012

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

В RootConfig.java:

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

В WebMvcConfig.java:

@ComponentScan(basePackages = { "com.myapp" },
    useDefaultFilters = false, includeFilters = @Filter(Controller.class))
9 голосов
/ 02 декабря 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...