Инициализация bean в Spring MVC
Я читаю документацию на официальном сайте Spring, на данный момент изучаю основы Spring core и мне уже немного известно про Spring MVC и меня беспокоит следующий вопрос, ответа на который я пока что не нашел, возможно из-за какого-то своего недопонимания. В официальной документации в примерах использования бинов пишется примерно следующее:
Инициализация через XML!
<!—-applCntx.xml—->
<bean id=“...” class=“...”/>
Далее в методе main мы инициализируем наш контейнер бинов
ApplicationContext context = new ClassPathXmlApplicationContext(“applCntx.xml”);
context.getBean(...)
Это все понятно и просто, но не понятно следующее:
На сколько мне известно, Spring MVC работает на основе сервлетов и следовательно метод main не нужен, точнее метод main находится «под капотом» Tomcat.
Как тогда происходит инициализации контейнера? Внутри самого Tomcat? К примеру мне нужно внедрение зависимости в контроллере:
@Controller
public class PetController{
//вот сюда надо внедрить зависимость
public TestClass clazz;
@GetMapping(“/“)
public String methodTest(DtoObj obj){
return clazz.getSomeThing(obj);
}
}
Как мне сделать это посредством именно XML конфигурации, без использования аннотаций (я понимаю, что сейчас пользуются практически только Java конфигурацией Spring без XML, но это же основы и мне важно понимать это)?
Ответы (1 шт):
Для начала небольшая вводная по war-приложениям (сервлеты их часть). Эти приложения поднимаются не командой java -jar твойДжаник.jar а специальной штукой, которая называется контейнер сервлетов. Это и есть тот самый Tomcat, Jetty/Netty или Undertow. Согласно спецификации сервлетов, контейнер сервлетов просканирует твоё приложение на предмет наличия классов, реализующих интерфейс javax.servlet.ServletContainerInitializer. Если таковые есть, то он создаст их и вызовет соответствующий метод в начале запуска приложения. Очень грубо можем назвать это аналогом метода main для war-приложения.
В spring имеется класс, реализующий данный интерфейс org.springframework.web.SpringServletContainerInitializer, который в свою очередь сканирует наличие классов, реализующих интерфейс org.springframework.web.WebApplicationInitializer, и запускает уже у них соответствующий метод.
Обратившись к официальной документации можно увидеть пример того, как инициализировать Spring внутри приложения
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) {
// Load Spring web application configuration
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
// Create and register the DispatcherServlet
DispatcherServlet servlet = new DispatcherServlet(context);
ServletRegistration.Dynamic registration = servletContext.addServlet("app", servlet);
registration.setLoadOnStartup(1);
registration.addMapping("/app/*");
}
}
Ну или в случаем xml-конфигурации та же документация говорит следующее
import org.springframework.web.WebApplicationInitializer;
public class MyWebApplicationInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext container) {
XmlWebApplicationContext appContext = new XmlWebApplicationContext();
appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext));
registration.setLoadOnStartup(1);
registration.addMapping("/");
}
}
где /WEB-INF/spring/dispatcher-config.xml - твоя xml-конфигурация для spring.
Т.е. контейнер сервлетов инициализирует приложение, которое в свою очередь внутри себя поднимает Spring.
Как объявить @Controller средствами xml?
Дело в том, что никак. Из-за сложности связывания методов и URI-путей, которые они обслуживают xml был бы переусложнён. Т.е. нет аналогий @GetMapping и ему подобных в xml-конфигурации.