Spring Framework

Spring AnnotationConfigApplicationContext AnnotationConfigWebApplicationContext 차이

데굴데굴. 2022. 1. 2. 01:16

기본적으로 스프링 부트는 컴포넌트 스캔을 지원한다.
이때 사용하는 application context는 AnnotationConfigApplicationContext 이다.
그리고 스프링 부트이면서 Spring MVC 의존성을 가진 프로젝트는 AnnotationConfigWebApplicationContext 을 사용한다.
javadoc 을 보면 그 둘은 web이냐 web이 아니냐의 차이만을 가질 뿐 equivalent 하다고 되어 있다.
그렇다면 둘은 WebApplicationContext 와 ApplicationContext의 차이점과 동일한 차이점을 가진다고 할 수 있다.
소스를 보면 둘은 인터페이스 AnnotationConfigRegistry 를 동일하게 implements 하고 있다.
이 인터페이스는 그냥 애노테이션이 달린 애들을 스캔(scan)하고 빈으로 등록(register)하는 메서드들이 선언되어 있는 애다.

AnnotationConfigWebApplicationContext
AbstractRefreshableWebApplicationContext <- AbstractRefreshableConfigApplicationContext <- AbstractRefreshableApplicationContext <- AbstractApplicationContext 를 extends 하고 있고

AnnotationConfigApplicationContext
GenericApplicationContext <- AbstractApplicationContext 를 extends 하고 있다.



AnnotationConfigWebApplicationContext 을 좀 뜯어보면 둘의 차이를 알 수 있다.

1. AbstractRefreshableApplicationContext <- AbstractApplicationContext

refresh(application context 초기화 시 실행되는 함수) 를 처음 호출 이후에도 여러 번 호출할 수 있게 해주는, refreshable application context 로의 기능 추가
=> 하지만 refresh가 여러 번 가능할 때의 이점과 web이 어떤 상관관계를 가지는지는 파악하지 못했다... 어떤 경우에 refresh가 필요할 때가 있다고는 하는데 어떤 경우일지..

AbstractRefreshableApplicationContext


    /**
     * This implementation performs an actual refresh of this context's underlying
     * bean factory, shutting down the previous bean factory (if any) and
     * initializing a fresh bean factory for the next phase of the context's lifecycle.
     */
    @Override
    protected final void refreshBeanFactory() throws BeansException {
        if (hasBeanFactory()) {
            destroyBeans();
            closeBeanFactory();
        }
        try {
            DefaultListableBeanFactory beanFactory = createBeanFactory();
            beanFactory.setSerializationId(getId());
            customizeBeanFactory(beanFactory);
            loadBeanDefinitions(beanFactory);
            this.beanFactory = beanFactory;
        }
        catch (IOException ex) {
            throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
        }
    }

2. AbstractRefreshableConfigApplicationContext <- AbstractRefreshableApplicationContext

xml config 파일의 위치를 받아서 application context를 설정하는 기능 추가

AbstractRefreshableConfigApplicationContext

    /**
     * Set the config locations for this application context.
     * <p>If not set, the implementation may use a default as appropriate.
     */
    public void setConfigLocations(@Nullable String... locations) {
        if (locations != null) {
            Assert.noNullElements(locations, "Config locations must not be null");
            this.configLocations = new String[locations.length];
            for (int i = 0; i < locations.length; i++) {
                this.configLocations[i] = resolvePath(locations[i]).trim();
            }
        }
        else {
            this.configLocations = null;
        }
    }

3. AbstractRefreshableWebApplicationContext <- AbstractRefreshableConfigApplicationContext

웹을 위한 서블릿 컨텍스트 기능 추가

@Override
    public void setServletContext(@Nullable ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    @Override
    @Nullable
    public ServletContext getServletContext() {
        return this.servletContext;
    }

    @Override
    public void setServletConfig(@Nullable ServletConfig servletConfig) {
        this.servletConfig = servletConfig;
        if (servletConfig != null && this.servletContext == null) {
            setServletContext(servletConfig.getServletContext());
        }
    }