스프링부트 해부학 : SpringBoot - @SpringBootApplication, SpringApplication

정윤성·2022년 6월 6일
0

스프링부트 해부학

목록 보기
9/20

역할

SpringBoot는 Spring과 다르게 Embedded Tomcat방식을 사용한다 따라서 SpringApplication은 Spring Container초기화뿐 아니라 WebServer생성 및 Servlet초기화 등의 여러작업을 포괄적으로 하게된다

@SpringBootApplication

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication

우리가 SpringBoot를 쉽게 사용할 수 있게 다양한 세팅이 되어있다

public @interface SpringBootConfiguration {
	@AliasFor(annotation = Configuration.class)
	boolean proxyBeanMethods() default true;
}

@Component는 Bean팩토리 메서드라도 같은 클래스 내부끼리 참조시 해당 Bean이아닌 메서드 자체를 가리킨다
반면 @Configuration은 내부적으로 AOP가 적용되어 해당 메서드에 접근시 자동으로 Bean을 호출하게 되어있는데 그 부분 설정이 위 Annotation이다

proxyBeanMethods를 false하게되면 @Configuration Method에선 더이상 CGLIB을 사용하지않는다

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

	Class<?>[] exclude() default {};

	String[] excludeName() default {};
}

@AutoConfigurationPackage를 통해 현재 해당 Annotation이 등록되어있는 Class를 기준으로 basePackage를 설정한다

@Import(AutoConfigurationImportSelector.class)같은경우

String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"

위 Path에 등록되어있는 설정클래스를 Bean, Listener 등으로 등록하고 exclude옵션을 통해 Configuration을 제외하는 등의 초기 설정에 대한 부분을 진행한다

마지막 @ComponentScan을 통해 basePackages를 기준으로 Scan을 진행한다

SpringApplication Constructor

public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	this.resourceLoader = resourceLoader;
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    this.bootstrapRegistryInitializers = new ArrayList<>(
    getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}

primarySources는 @SpringBootApplication이 붙어있는 클래스를 나타낸다
webApplicationType은 Servlet, WebFlux, No 일케 세가지가 있다
boostrapRegistryInitializers는 spring.factories에 있는 내용을 불러온다
mainApplicationClass는 static main 메서드가 있는 클래스를 나타낸다

SpringApplication run

public ConfigurableApplicationContext run(String... args) {
	long startTime = System.nanoTime(); // 1
    ...
    SpringApplicationRunListeners listeners = getRunListeners(args); // 2
    listeners.starting(bootstrapContext, this.mainApplicationClass); // 3
    ApplicationArguments applicationArguments = new  DefaultApplicationArguments(args); // 4
    ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments); // 5
    configureIgnoreBeanInfo(environment); // 6
    Banner printedBanner = printBanner(environment); // 7
    context = createApplicationContext(); // 8
    prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner); // 9
    refreshContext(context); // 10
    Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime); // 11
    listeners.started(context, timeTakenToStartup); // 12
    callRunners(context, applicationArguments); // 13
}
  1. 총 시작시간을 알아보기 위해 startTime지정
  2. spring.factories를 기반으로 RunListener를 불러온다 ( Spring이 run중일 때 Listener )
  3. Run이 starting했다는 Event publish
  4. args를 Wrapper클래스로 감싼다
  5. 우리가 설정한 application.yml파일을 불러들인다 ( 이외 기타 초기설정도 진행함 )
  6. ignore할 environment 진행
  7. Spring이 시작할때 Banner띄어주는 부분
    • spring.banner.location : 배너의 위치 property
    • spring.banner.image.location("gif", "jpg", "png") : 이미지로 할시 이미지 property
    • banner.txt : default location
  8. RootContext를 생성합니다
    • Servlet : AnnotationConfigServletWebServerApplicationContext ( DispatchServlet )
    • WebFlux : AnnotationConfigReactiveWebServerApplicationContext ( DispatcherHandler )
    • None : AnnotationConfigApplicationContext ( Batch )
  9. Configuration, ResourceLoader, Initializers, Banner, PostProcessor 등의 기본적인 Bean등록 ( 이때 Bootstrap Context는 close됨 )
  10. 각종 Bean들 초기화 ( 이전까지 IoC에서 했던 작업들이 여기서 실행 됨 )
  11. 시간 측정 종료
  12. Listener에의해 시간출력
  13. ApplicationRunner, CommandLineRunner 실행

정리

  1. @SpringBootApplication가 무엇인지 알 수 있었다
  2. 간략하지만 run의 실행순서정도는 알 수 있었다

마무리

사실 이 파트는 property지정부터 refresh하는 부분에 대해 좀더 자세하게 알아볼 수 있었지만 사실 그렇게까지 할필요성은 없을거같아서 간략하게 실행순서 정도로만 알아봤습니다

profile
게으른 개발자

0개의 댓글