스프링부트 해부학 : RequestFlow(번외) - Filter

정윤성·2022년 6월 4일
0

스프링부트 해부학

목록 보기
4/20

시작

스프링 컨테이너에 앞서 RequestFlow 최전방을 담당하는 Filter에 대해서 먼저 알아보고 가겠습니다


역할

출처 : https://devlog-wjdrbs96.tistory.com/352

Filter는 Spring이아닌 Servlet에서 제공해주는 기능이다 따라서 Spring에서 사용하려면 Spring에서 제공해주는 FilterRegistraionBean을 이용해 FilterChain에 등록시켜 사용해야 한다


Init

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());

Process

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를 통해 재귀적으로 처리된다 )


정리

  1. Filter같은경우 Servlet에서 사용하는 기능이고 이를 Spring에서 Adapter를 이용해 접근하는 방식으로 처리한다 ( 그냥 Filter는 Servlet의 기능이라고만 생각하자 )
  2. 우리가 이전에 알아봤던 Interceptor, BeanPostProcessor, Handler, Resolver 등은 전부 Spring에서 처리되고 Filter만 Servlet단에서 처리되는걸 알 수 있다
profile
게으른 개발자

0개의 댓글