티스토리 뷰
직접 공부하며 정리한 내용이라 틀린 내용이 있을 수 있습니다!
JavaConfig방식을 통해 스프링이 구동되는 순서를 알아보자.
먼저 xml설정일 때의 예로, 전체적인 그림을 보면 다음과 같다.
웹 어플리케이션 실행
웹 어플리케이션이 실행되면 톰캣에 의해 web.xml
이 로딩되면서 스프링 구동된다.
Java Config방식에서는 web.xml의 역할을 할 클래스를 만들어야 한다.
이는 WebApplicationInitializer
인터페이스를 구현하여 onStartup
메소드를 작성하면 된다.
public class WebApplication implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) {}
}
이곳이 web.xml
의 역할을 하는 entry point가 된다.
onStartup
메소드에서는 톰캣에서 관리하는 서블릿 컨테이너
가 ServletContext
로 들어온다.
ContextLoaderListener
web.xml
에는 ContextLoaderListener
가 등록되어 있다.
우리는 JAVA코드 내에서 직접 위 클래스를 만들어 사용한다.
ContextLoaderListener contextLoaderListener = new ContextLoaderListener(rootContext);
servletContext.addListener(contextLoaderListener);
contextLoaderListener
를 생성한 후에 서블릿 컨테이너
에 등록한다.rootContext
는 이후에 설명하겠다.
ContextLoaderListener
는 ApplicationContext
를 생성하는 역할을 수행한다.
즉, 스프링 컨테이너를 생성하고 관리하기 위해 ContextLoaderListener
를 이용한다.
root-context
이제 스프링 컨테이너를 구동시켜보자.
xml방식에서는 root-context.xml
혹은 applicationContext.xml
파일을 로딩해 스프링 컨테이너를 구동하게 된다. 위 설정 파일에는 스프링 컨테이너에 등록할 빈의 정보들이 명시되어 있다
이렇게 구동된 스프링 컨테이너를 루트 컨테이너
라고 한다.
그리고 루트 컨테이너
를 등록할 때는 web과 관련된 빈들은 등록하지 않는다.
우리는 Java Config방식을 사용하므로 applicationContext.xml
역할을 할 클래스를 만들자.
ApplicationConfiguration
라는 이름으로 클래스를 만들었다. 내용은 다음과 같다.
@Import({DbConfiguration.class})
@PropertySource("classpath:application.properties")
@Configuration
@ComponentScan({"com.aram.smartstore.**.service"})
public class ApplicationConfiguration {}
빈을 등록할 때는 컴포넌트 스캔
방식을 사용하기에 클래스 내부에 직접 빈을 등록하지 않았다.
만약 직접 빈을 등록한다면 ApplicationConfiguration
클래스 내에 @Bean
어노테이션을 이용해 등록하면 된다.
위처럼 컴포넌트 스캔
방식을 사용하게 되면 com.aram.smartstore.**.service
에 해당하는 클래스 중 @Component
어노테이션이 붙은 클래스를 자동으로 빈에 등록한다.
@Import({DbConfiguration.class})
는 DB관련 설정을 담고 있는 DbConfiguration
클래스도 ApplicationConfiguration
가 로딩되는 시점에 import하여 함께 로딩하겠다는 말이다.
따라서, DbConfiguration
에 등록되어 있는 빈들도 스프링 컨테이너에 등록된다.
DB configuration
나는 DB관련 설정도 해줬기에 다음처럼 DB연결을 위해 사용할 빈들을 등록해 주었다.
@Configuration
@MapperScan({"com.**.mapper"})
public class DbConfiguration {
@Value("${db.driverClassName}")
private String driverClassName;
@Value("${db.url}")
private String url;
@Value("${db.username}")
private String username;
@Value("${db.password}")
private String password;
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setDriverClassName(driverClassName);
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource, ApplicationContext applicationContext) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource);
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
configuration.setMapUnderscoreToCamelCase(true);
factoryBean.setConfiguration(configuration);
// factoryBean.setTypeAliasesPackage("com.**.dto");
// factoryBean.setMapperLocations(applicationContext.getResources("classpath:com/**/mapper/*.xml"));
return factoryBean.getObject();
}
}
이제 ApplicationConfiguration
에서 위 설정을 @Import
하고 있으므로 ApplicationConfiguration
와 DB에 있는 빈이 함께 스프링 컨테이너에 등록된다.
Application Context 생성
다시 WebApplication
으로 돌아와서 위에서 만든 설정파일들을 통해 스프링 컨테이너를 생성하자.
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(ApplicationConfiguration.class);
rootContext
라는 이름으로 스프링 컨테이너를 만들었다. 이때 ApplicationConfiguration
가 사용되는데 이 내부에 DB관련 설정도 함께 포함되어 있다.
이제 아까 사용했던 new ContextLoaderListener(rootContext);
코드가 이해 될 것이다.
ContextLoaderListener
는 위 스프링 컨테이너를 생성하고 관리하는 역할을 하게 된다.
여기까지 하게 되면 아래 그림의 (4)번 까지 하게 된 것이다.
서블릿 컨테이너에 ContextLoaderListener
를 등록하고 ContextLoaderListener
는 rootContext
라는 이름의 스프링 컨테이너를 생성하고 관리하고 있다.
클라이언트로 부터 웹 어플리케이션 요청이 옴
위에서 rootContext
를 생성할 때 web과 관련된 빈은 등록하지 않았다.
따라서 지금 상태로는 클라이언트로 부터 어떤 요청이 오더라도 해당 요청을 받아줄 컨트롤러가 없다.
먼저 클라이언트로 요청이 올 때 해당 요청을 받아 적절한 처리를 해줄 DispatcherServlet
이 필요하다.
디스패처 서블릿은 FrontController의 역할을 수행하여 클라이언트로 온 HTTP메세지를 분석해 알맞은 Controller에게 전달하고, 응답을 받아 응답해주는 역할을 수행한다.
먼저 디스패처 서블렛을 생성하자.
DispatcherServlet dispatcherServlet = new DispatcherServlet();
디스패처 서블릿은 컨트롤러와 관련된 빈들을 관리할 스프링 컨테이너를 구동한다.
따라서, web과 관련된 설정을 담고 있는(컨트롤러 빈을 관리할) 클래스를 만들자.
WebMvcConfigurer
를 구현한 WebConfiguration
클래스를 만들었다.
@Configuration
@EnableWebMvc
@ComponentScan({"com.aram.smartstore.**.controller"})
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new MappingJackson2HttpMessageConverter());
}
}
@Configuration
와 @EnableWebMvc
어노테이션을 붙이면 된다.@ComponentScan({"com.aram.smartstore.**.controller"})
에 의해 컨트롤러 빈이 스프링 컨테이너에 등록된다.
나는 컨버터를 MappingJackson2HttpMessageConverter
로 설정했다.
이제 위 설정클래스를 이용해 ApplicationContext를 만들자. 방식은 rootContext와 같다.
AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
webContext.register(WebConfiguration.class);
webContext
라는 이름으로 ApplicationContext를 만들었다.
이제 앞서 생성한 디스패처 서블릿에 해당 context를 추가하면 된다.
dispatcherServlet.setApplicationContext(webContext);
이렇게 디스패처 서블릿을 생성하는 것 까지 완료했다.
서블릿 컨테이너에 디스패처 서블릿 추가
이제 서블릿 컨테이너에 앞서 만든 디스패처 서블릿을 추가하자.
ServletRegistration dispatcher = servletContext.addServlet("dispatcher", dispatcherServlet);
이제 모든 그림이 완성되었다.
클라이언트로 요청이 온다면 디스패처 서블릿
이 만들어지게 되고, 디스패처 서블릿은 WebConfiguration
를 로딩하여 컨트롤러를 관리하는 스프링 컨테이너를 만들게 된다.
이제 디스패처 서블릿은 클라이언트로 부터 온 요청을 분석하여 알맞은 컨트롤러에 보내고 응답 결과를 클라이언트로 보내주는 역할을 하게 된다.
이렇게하여 스프링 컨테이너가 어떤식으로 동작되는지 확인할 수 있었다.
'Spring' 카테고리의 다른 글
[Spring] 스프링 필터와 인터셉터(Filter, Interceptor) (0) | 2022.05.09 |
---|---|
[SpringBoot] 예외처리 방법 (@ControllerAdvice, @ExceptionHandler) (0) | 2022.04.08 |
[Spring] Junit5 단위 테스트(Unit Test) 작성 (0) | 2022.04.02 |
[SpringBoot] 스프링부트 WebSocket(웹소켓) 사용하기 (0) | 2022.03.29 |
- Total
- Today
- Yesterday
- 컴퓨터 통신
- 중앙대학교
- node.js
- nodeJS
- java
- 백트래킹
- 그래프
- 벨만포드
- 시뮬레이션
- 스레드
- 자바
- 구현
- 예외처리
- Computer Architecture
- 세그먼트 트리
- ReactNative
- nestjs
- nest.js
- BFS
- dfs
- 백준
- 동적계획법
- 재귀
- boj
- 자바스크립트
- typeORM
- 투포인터
- 알고리즘
- 그리디
- 컴퓨터 구조
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |