woniper

Spring Boot SpringApplication Class 본문

Spring

Spring Boot SpringApplication Class

woniper1 2016. 7. 27. 14:20

  스프링 부트가 요즘 굉장히 핫!! 하다.

MSA가 유행하면서 그에 발맞춰 여러가지 프로젝트가 쏱아져 나오는 느낌이랄까? 스프링 부트가 처음 나왔을때 굉장히 충격이였다. 내가 처음 스프링을 접했을 때에는 설정이 너무 어렵고 왜 이렇게 복잡한 설정을 해야만 겨우겨우 request를 한번 날릴 수 있을까 생각했었다. 스프링 부트는 이런 어려운 설정을 자동으로 해준다. 부트가 이런 장점만 있는건 아니지만 가장 눈에 띄는 장점 중 하나 아닐까 생각된다.


  오늘은 스프링 부트 기반 프로젝트를 실행하기 위해 필요한 SpringApplication라는 class를 살펴보았다. 먼저 SpringApplication Class를 이용해 실행하는 코드를 보자.

1
2
3
4
5
6
7
8
@SpringBootApplication
public class TestApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
 
}
cs

  스프링을 실행하기 위해서 복잡했던 설정 코드 대신 위에 코드가 전부다. main 메소드에서 실행하는 SpringApplication.run 메소드를 살펴볼 예정이다.

파라미터로 실행 대상인 TestApplicatioin.class와 main 메소드 파라미터인 args를 넘긴다. run 메소드에서는 어떤 일을 할까?


  1. MainClass 셋팅
  2. ApplicationContext(정확히는 ConfigurableApplicationContext) 생성 및 refresh
MainClass 셋팅
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private Class<?> deduceMainApplicationClass() {
    try {
        StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
        for (StackTraceElement stackTraceElement : stackTrace) {
            if ("main".equals(stackTraceElement.getMethodName())) {
                return Class.forName(stackTraceElement.getClassName());
            }
        }
    }
    catch (ClassNotFoundException ex) {
        // Swallow and continue
    }
    return null;
}
cs

  run 메소드에 파라미터로 넘어가는 TestApplication.class를 mainClass로 셋팅을한다. class를 타입을 넘겨 바로 mainClass로 셋팅하는 줄 알았는데, 그렇지 않고 위 코드와 같이 StackTrace를 생성해 main 메소드를 갖는 클래스를 찾아 셋팅한다.


ConfigurableApplicaitonContext 생성 및 refresh

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
public ConfigurableApplicationContext run(String... args) {
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    configureHeadlessProperty();
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.started();
    try {
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        Banner printedBanner = printBanner(environment);
        context = createApplicationContext();
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        refreshContext(context);
        afterRefresh(context, applicationArguments);
        listeners.finished(context, null);
        stopWatch.stop();
        if (this.logStartupInfo) {
            new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }
        return context;
    }
    catch (Throwable ex) {
        handleRunFailure(context, listeners, ex);
        throw new IllegalStateException(ex);
    }
}
cs

  이 부분을 이해하기 위해서는 먼저 ApplicationContext를 이해해야하는데, 이 부분 설명은 생략하고 참고 URL을 보기바란다. (이 글에 설명하기에는 너무 방대한 양이기도 하고 어려운 내용이기도하다.)

  run 메소드를 실행하면 실제로 실행되는 코드이다. ConfigurableApplicationContext를 생성하기 위해 createApplicationContext 메소드(12라인)를 실행해 생성 후 refreshContext 메소드(14라인)를 실행하는 것을 알 수 있다.

  refreshContext 메소드를 실행하면 실제로 실행되는 refresh 메소드는 AbstractApplicationContext로 형변환 후 refresh 메소드를 호출 하는 것을 알 수 있다.

1
2
3
4
protected void refresh(ApplicationContext applicationContext) {
    Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
    ((AbstractApplicationContext) applicationContext).refresh();
}
cs

    SpringApplication Class 보며 짐작 할 수 있는 것은 SpringApplication Class는 실제로는 ConfigurableApplicationContext를 가지고 refresh 메소드를 실행시켜 스프링을 구동 시키는 것을 알 수 있다. 

Comments