src/main/java/woowacourse/Application.java

package woowacourse;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

메인 클래스에 있는 @SpringBootApplication 어노테이션은 크게 3개의 어노테이션이 합쳐진 것이다.

org/springframework/boot/autoconfigure/SpringBootApplication.java

package org.springframework.boot.autoconfigure;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.core.annotation.AliasFor;
import org.springframework.data.repository.Repository;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {

	@AliasFor(annotation = EnableAutoConfiguration.class)
	Class<?>[] exclude() default {};

	@AliasFor(annotation = EnableAutoConfiguration.class)
	String[] excludeName() default {};

	@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
	String[] scanBasePackages() default {};

	@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
	Class<?>[] scanBasePackageClasses() default {};

	@AliasFor(annotation = ComponentScan.class, attribute = "nameGenerator")
	Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

	@AliasFor(annotation = Configuration.class)
	boolean proxyBeanMethods() default true;

}

Spring Boot Application 은 Bean 을 2번 등록한다. ComponentScan 으로 등록하고, 그 후에 EnableAutoConfiguration 으로 추가적인 Bean 을 읽어서 등록한다.

@ComponentScan

해당 패키지에서 @Component 어노테이션을 가진 Bean 들을 스캔해서 등록한다. @Configuration, @Repository, @Service, @Controller, @RestController 등이 있다.

@EnableAutoConfiguration

Spring Boot 의 meta 파일(spring.factories)을 읽어서, 미리 정의되어 있는 자바 설정 파일(@Configuration)들을 빈으로 등록하는 역할을 수행한다.

https://velog.io/@max9106/Spring-Boot-EnableAutoConfiguration

https://cornswrold.tistory.com/314

@SpringBootConfiguration

이 클래스가 Spring Boot Application 의 @Configuration 을 제공한다는 것을 나타낸다. Application 을 통틀어 단 하나만 선언되어야 한다.

https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/SpringBootConfiguration.html