SpringBoot는 Spring과 다르게 Embedded Tomcat방식을 사용한다 따라서 SpringApplication은 Spring Container초기화뿐 아니라 WebServer생성 및 Servlet초기화 등의 여러작업을 포괄적으로 하게된다
@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을 진행한다
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 메서드가 있는 클래스를 나타낸다
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
}
사실 이 파트는 property지정부터 refresh하는 부분에 대해 좀더 자세하게 알아볼 수 있었지만 사실 그렇게까지 할필요성은 없을거같아서 간략하게 실행순서 정도로만 알아봤습니다