스프링 컨테이너에 앞서 RequestFlow 최전방을 담당하는 Filter에 대해서 먼저 알아보고 가겠습니다
출처 : https://devlog-wjdrbs96.tistory.com/352
Filter는 Spring이아닌 Servlet에서 제공해주는 기능이다 따라서 Spring에서 사용하려면 Spring에서 제공해주는 FilterRegistraionBean을 이용해 FilterChain에 등록시켜 사용해야 한다
ServletWebServerApplicationContext.class
private void createWebServer() {
...
this.webServer = factory.getWebServer(getSelfInitializer());
...
}
private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {
return this::selfInitialize;
}
private void selfInitialize(ServletContext servletContext) throws ServletException {
for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
beans.onStartup(servletContext);
}
}
protected Collection<ServletContextInitializer> getServletContextInitializerBeans() {
return new ServletContextInitializerBeans(getBeanFactory());
}
ServletContextInitializerBeans.class
public ServletContextInitializerBeans(ListableBeanFactory beanFactory,
Class<? extends ServletContextInitializer>... initializerTypes) {
...
addServletContextInitializerBeans(beanFactory);
addAdaptableBeans(beanFactory);
...
}
addServletContextInitializerBeans메서드는 실제 ServletContext를 구성하는데 필요한 정보를 SpringBean으로 등록하는 작업이다
addAdaptableBeans는 실제 Servlet Container에 필터나, 리스너를 등록할 수 있게 도와주는 Bean이다
addAdaptableBeans를 조금더 보면
protected void addAdaptableBeans(ListableBeanFactory beanFactory) {
...
addAsRegistrationBean(beanFactory, Servlet.class, new ServletRegistrationBeanAdapter(multipartConfig));
addAsRegistrationBean(beanFactory, Filter.class, new FilterRegistrationBeanAdapter());
for (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes()) {
addAsRegistrationBean(beanFactory, EventListener.class, (Class<EventListener>) listenerType,
new ServletListenerRegistrationBeanAdapter());
}
}
다음과같이 Filter, Servlet, EventListener에 관련된 Bean을 등록하는걸 볼 수 있다
실제 Filter관련으로 디버깅을 해보면
다음과같이 정상적으로 등록되는걸 볼 수 있다최종적으로 StandardContext.class에서 FilterRegistration의 내용을 토대로 Context에 저장시키는걸 볼 수 있다
ApplicationFilterConfig filterConfig =
new ApplicationFilterConfig(this, entry.getValue());
StandardWrapperValue.class
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
...
ApplicationFilterChain filterChain =
ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
...
filterChain.doFilter(request.getRequest(), response.getResponse());
}
해당 클래스는 실제 서블릿 컨테이너에서 관리하는 내용이며 ApplicationFilterChain을 만든 뒤 부트스트랩하여 가져온 Spring Filter들을 순차적으로 적용시킨다
즉 Servlet Container에 Request가 오면 FilterChain을 생성해 처리한다고 보면된다
( FilterChain은 doFilter를 통해 재귀적으로 처리된다 )