์์ ์๋ฐ ํด๋์ค์ ์ด๋ ธํ ์ด์ ์ ์ด์ฉํ ์๋
0. ๊ฐ์
Servlet 3.0 ์ด์ ๋ฒ์ ๋ถํฐ๋ web.xml ์์ด ์๋ธ๋ฆฟ ์ปจํ ์คํธ๋ฅผ ์ด๊ธฐํํ ์ ์๋ ๋ฐฉ๋ฒ์ด ๋์์ต๋๋ค. ๋ฐ๋ผ์ servlet, filter, listener ์ปดํฌ๋ํธ์ ๋ฑ๋ก๊ณผ ์ค์ ์ ์ฝ๋๋ก ์ ๋ ฅํ์ฌ ์ฌ์ฉ ๊ฐ๋ฅํ๊ณ web.xml ํ์ผ๊ณผ ๊ฐ์ด ์ฌ์ฉํ ์ ๋ ์์ต๋๋ค.
๊ทธ๋์ ServletContext์ ๊ด๋ จ ๋ฉ์๋๋ค์ด ์ถ๊ฐ๋์์ต๋๋ค. ์ด ๋ฉ์๋๋ค์ ์ฌ์ฉํ๊ธฐ ์ํด์ ServletContainerInitializer์ onStartup ๋ฉ์๋๋ฅผ ์ ์ ํ๊ฒ ํธ์ถํ๋ฉด ๋ฉ๋๋ค. ์ฝ๋๋ก ์ค์ ํ๋ ๊ฒ์ ์ฅ์ ์ ์ต์ข ์ฌ์ฉ์๋ ์ดํ๋ฆฌ์ผ์ด์ ์ด DD(deployment descriptor, ์ผ๋ช web.xml)๋ฅผ ๋ฐฐํฌํ์ง ์๊ณ ๋ ํ๋ ์์ํฌ์ web component๋ค์ ์๋์ ์ผ๋ก ์ถ๊ฐํ ์ ์๋ค๋ ์ ์ ๋๋ค. Spring Framework๋ SpringServletContainerInitializer๋ฅผ ํตํด ์ด ์ ๋ต์ ์ฌ์ฉํฉ๋๋ค.
WAS ๊ฐ ์์๋ ๋ ํ์ํ ์ค์ ๋ค์ด ์์๋๋ ๊ณณ์ด ๋ฐฐํฌ ์ค๋ช ์(Deploy Descriptor)์ธ web.xml ํ์ผ์ ๋๋ค.
ServletContainInitializer
package javax.servlet;
...
public interface ServletContainerInitializer {
public void onStartup(Set<Class<?>> c, ServletContext ctx)
throws ServletException;
}
servlet 3.0 spec
- ์๋ฒ ์คํ ์ ServletContainerInitializer service provider๋ฅผ ์ฐพ์๋ค @HandleTypes๋ก ์ ์๋ ํด๋์ค๋ฅผ ์คํ
javax.servlet.ServletContainerInitializer ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ ํด๋์ค๋ฅผ ๋ง๋ค๊ณ ,
spring-web-{ RELEASE-VERSION }/META-INF/services/javax.servlet.ServletContainerInitializer ํ์ผ์ ํจํค์ง๋ฅผ ํฌํจํ ํด๋์ค๋ช
์ ์ ์ฅ. (์คํ๋ง์์๋ "org.springframework.web.SpringServletContainerInitializer" ๋ฅผ ์ ์ฅํ๊ณ ์๋ค.)
META-INF/service ์์ ์ ๊ณตํ๊ณ ์ ํ๋ ์๋น์ค๋ช ์ ํ์ผ์ ๋ฃ๊ณ , ๋ด์ฉ์ผ๋ก ๊ทธ๊ฒ์ ๊ตฌํํ ํด๋์ค๋ฅผ ๋ฃ์ด ์๋น์ค ์ ๊ณต(Service Provider)
SpringServletContainerInitializer
package org.springframework.web;
import ...
@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
@Override
public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
throws ServletException {
List<WebApplicationInitializer> initializers = new LinkedList<>();
if (webAppInitializerClasses != null) {
for (Class<?> waiClass : webAppInitializerClasses) {
// Be defensive: Some servlet containers provide us with invalid classes,
// no matter what @HandlesTypes says...
if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
try {
initializers.add((WebApplicationInitializer)
ReflectionUtils.accessibleConstructor(waiClass).newInstance());
}
catch (Throwable ex) {
throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
}
}
}
}
if (initializers.isEmpty()) {
servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
return;
}
servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
AnnotationAwareOrderComparator.sort(initializers);
for (WebApplicationInitializer initializer : initializers) {
initializer.onStartup(servletContext);
}
}
}
- @HandleTypes์ ์ ์๋ ํด๋์ค ํน์ ๊ตฌ์ฒด์ ์ผ๋ก ๊ตฌํ ๋ ํ์ ํด๋์ค๋ค์ SpringServletContainerInitializer ํด๋์ค์ onStartup()๋ฉ์๋๋ฅผ ํตํด Set<Class<?>> ์์ผ๋ก ๋ค์ด์จ๋ค.
- if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) && WebApplicationInitializer.class.isAssignableFrom(waiClass))
- waiClass๊ฐ ์ธํฐํ์ด์ค๊ฐ ์๋๊ณ , ์ถ์ ํด๋์ค๋ ์๋ ๊ฒฝ์ฐ์๋ง WebApplicationInitializer๋ฅผ ์์ฑํ๋ค.
- ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ Set<Class<?>> ์ ๋ฐ๋ณตํด์ WebApplicationInitializer๋ก ์์ฑ(newInstance)ํด initializers list์ ๋ด๋๋ค.
- initializers list๋ฅผ ์ ๋ ฌํด WebApplicationInitializer#onStartup ๋ฉ์๋๋ฅผ ์คํํ๋ค.
ServletContainerInitializer์ @HandleTypes์ ์ฌ์ฉ์ผ๋ก IOC ํจํด์ ์ ์ฉํ๋ ๊ฒ์ด ๊ฐ๋ฅํด์ง ๊ฒ.
๊ฐ๋ฐ์๋ ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์ jar ์์กด์ฑ๊ณผ POJO(์ด๋ ธํ ์ด์ ์ด๋ ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด)๋ฅผ ๊ฒฐํฉํ๊ธฐ๋ง ํ๋ฉด ๋์ ๋๋ค.
๊ทธ๋ฌ๋ฏ๋ก, ์คํ๋งํ๋ ์์์ xml ์์ด ์คํํ๊ธฐ ์ํด์๋ org.springframework.web.WebApplicationInitializer๋ฅผ ๊ตฌํํ๋ ํด๋์ค๋ฅผ ๋ง๋ค์ด์ฃผ๋ฉด ๋๋ ๊ฒ์ ๋๋ค.
์์ฝ
- Spring-MVC์์ ์๋ธ๋ฆฟ ๊ธฐ๋ฐ์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ค์ ์ ๋ด๋นํ๋ ๊ตฌํ์ฒด๋ ServletContainerInitializer ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ SpringServletContainerInitializer ํด๋์ค๋ค.
- SpringServletContainerInitializer#onStartup ๋ฉ์๋๋ WebApplicationInitializer ์ธํฐํ์ด์ค๋ฅผ ์์ํ (์ธํฐํ์ด์ค, ์ถ์ ํด๋์ค๊ฐ ์๋)์ผ๋ฐ ํด๋์ค๋ฅผ ์์ฑํ๋ค.
- WebApplicationInitializer ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ AbstractContextLoaderInitializer, AbstractDispatcherServletInitializer, AbstractAnnotationConfigDispatcherServletInitializer ์ถ์ ํด๋์ค๋ค.
- ์น ์ ํ๋ฆฌ์ผ์ด์ ์ค์ ์ ์ํด WebApplicationInitializer ์ธํฐํ์ด์ค๋ฅผ ์์ํ JavaConfig(WebConfig) ํด๋์ค๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค.
- SpringServletContainerInitializer#onStartup ๋ฉ์๋์์ ์์ฑ๋๋ WebApplicationInitializer ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ ์ฐ๋ฆฌ๊ฐ ๋ง๋ WebConfig ๊ตฌํ์ฒด๋ก ์์ฑ๋๋ค.
Ref.
- ํฐ์บฃ์ด ์ด๋ป๊ฒ Spring Framework์ ์ฐพ์๋ด๊ณ ์ด๊ธฐํ ํ๋์ง?
https://medium.com/chequer/tomcat-spring-bootstrapping-sequence-2%ED%8E%B8-spring-e19705529132
https://offbyone.tistory.com/215
https://akaroice.tistory.com/13
https://escapefromcoding.tistory.com/174
AbstractContextLoaderInitializer
https://blog.woniper.net/367?category=699184
AbstractDispatcherServletInitializerแแ ช AbstractAnnotationConfigDispatcherServletInitializer