Я прочитал:
Многокомпонентное сканирование
В чем разница между ApplicationContext и WebApplicationContext в Spring MVC?
аннотация @RequestMapping не работает, если ‹context:component-scan /› находится в контексте приложения, а не в контексте диспетчера (подробнее об этом один позже)
и несколько других, но ни один из них не отвечает на вопрос:
Почему область действия <context:component-scan.../>
ограничена, когда она присутствует в контексте ROOT приложения Spring MVC?
Насколько я понимаю, он вызывает сканирование всех классов в указанных пакетах и создает экземпляры любых bean-компонентов, стереотипных с @Component
или любым из его подстереотипов (@Repository
, @Service
и @Controller
).
Дано:
applicationContext.xml (корневой контекст)
<beans...>
...
<context:component-scan base-package="com.myproject"/>
<context:property-placeholder
ignore-resource-not-found="true"
location="classpath:default.properties, file:///etc/gallery/gallery.properties"/>
</beans>
main-servlet.xml (контекст сервлета)
<beans ...>
...
<mvc:annotation-driven/>
<mvc:resources mapping="/image/**" location="file:/${gallery.location}" />
<mvc:resources mapping="/css/**" location="/css/"/>
<mvc:resources mapping="/js/**" location="/js/"/>
<mvc:resources mapping="/images/**" location="/images/"/>
...
</beans>
com/myproject/web/MainController.java
package com.myproject.web;
@Controller
public class MainController
{
...
@RequestMapping("/gallery/**")
public String gallery(ModelMap modelMap, HttpServletRequest req, HttpServletResponse resp) throws IOException
{
...
}
}
Документы Spring утверждают, что любые bean-компоненты, созданные в корневом контексте, являются общими и доступными для отдельных контекстов приложения сервлета. Таким образом, два объявления <context:...>
в корневом контексте должны привести к созданию bean-компонентов, видимых в контексте сервлета. Но, похоже, это не так. Мне нужно повторить ОБА <context:component-scan.../>
и <context:property-placeholder.../>
в контексте сервлета.
Отсутствие <context:component-scan.../>
в контексте сервлета приводит к
Sep 15, 2015 10:08:16 AM org.springframework.web.servlet.PageNotFound noHandlerFound
WARNING: No mapping found for HTTP request with URI [/gallery/habitat/20150813] in DispatcherServlet with name 'main'
Sep 15, 2015 10:08:16 AM org.springframework.web.servlet.PageNotFound noHandlerFound
WARNING: No mapping found for HTTP request with URI [/error] in DispatcherServlet with name 'main'
указывая на то, что @Controller
не был решен.
Отсутствие <context:property-placeholder.../>
приводит к тому, что аннотация @Value
с использованием ссылки на свойство не обрабатывается, что в моем случае приводит к некоторым неработающим ссылкам.
Поскольку обе эти директивы <context:.../>
приводят к созданию экземпляров bean-компонентов, я не понимаю, почему bean-компоненты не видны в дочернем контексте, что прямо противоречит документации. Кроме того, разве наличие двух операторов component-scan
не приводит к тому, что экземпляр bean-компонента контроллера создается дважды?
Что касается аннотации @RequestMapping, которая не работает, если ‹context:component-scan /› находится в контексте приложения, а не в контексте диспетчера, У меня есть <mvc:annotation-driven />
в контексте моего приложения, и ответы здесь не объясняют, ПОЧЕМУ необходимы два оператора component-scan
.
Мне действительно неудобно использовать «магию», если я полностью не понимаю, как она работает, и не могу предсказать, как она будет себя вести, когда я что-то подправлю. Таким образом, «решение» «просто добавьте его в обоих местах и двигайтесь дальше» неприемлемо.