@SpringBootApplication 이란?
spring boot 프로젝트를 생성하면 프로젝트_이름Application.java가 자동으로 생성이 되고 코드를 확인해보면 @SpringBootApplication 이 있는것을 확인 할 수 있습니다.
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(TestApplication.class, args);
}
}
아래의 이미지는 @SpringBootApplication 의 내부 구현 코드입니다.
@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;
}
@SpringBootApplication 어노테이션을 통해 설정한 값들은 각각 다음의 기능으로 연결되어 동작합니다.
- exclude : 특정 클래스를 자동 설정에서 제외함
- excludeName : 클래스의 이름으로 자동 설정에서 제외함
- scanBasePackages :컴포넌트 스캔(빈 탐색)을 진행할 베이스 패키지를 설정함
- scanBasePackageClasses : 컴포넌트 스캔(빈 탐색)을 진행할 베이스 클래스를 설정함
- nameGenerator : 빈 이름 생성을 담당할 클래스를 설정함
- proxyBeanMethods : @Bean 메소드를 프록시 방식으로 처리하도록 설정함
proxyBeanMethods 란?
proxyBeanMethods는 @Bean 으로 빈을 등록하는 메소드에 프록시 패턴을 적용할 것인지를 결정하는 속성입니다.
proxyBeanMethods의 기본값은 true이며, 별다른 설정을 하지 않았다면 @Bean 메소드에 프록시가 기본으로 적용됩니다.
@Bean 메소드에 프록시가 필요한 이유는 해당 메소드를 직접 호출하는 경우에도 항상 싱글톤 스코프를 강제하여 1개의 객체만을 생성하기 위함입니다.
@Configuration(proxyBeanMethods = false)
public class MyBeanConfiguration {
@Bean
public CommonBean commonBean() {
return new CommonBean();
}
@Bean
public MyFirstBean myFirstBean() {
return new MyFirstBean(commonBean());
}
@Bean
public MySecondBean mySecondBean() {
return new MySecondBean(commonBean());
}
}
위의 코드에서 우리는 CommonBean 객체를 생성하는 commonBean() 메소드를 직접 호출하고 있습니다. 만약 proxyBeanMethods를 false로 설정하면 MyBeanConfiguration 클래스에 프록시가 적용되지 않아 총 2개의 CommonBean이 생성이 됩니다. 이렇게 여러 개의 빈이 생성되는 상황은 일반적으로 우리가 원하는 그림이 아닙니다. 스프링은 그래서 기본적으로 proxyBeanMethods를 true로 설정하고 바이트 조작 라이브러리인 CGLib을 통해 프록시 패턴을 적용합니다. 그래서 해당 @Bean 메소드가 호출되어 이미 빈이 생성되었으면 존재하는 빈을 찾아서 반환함으로써 1개의 빈이 생성되도록 처리합니다.
위 어노테이션의 구현을 보면 다음과 같이 3가지 어노테이션이 명시되어 있습니다.
- @SpringBootConfiguration
- @EnableAutoConfiguration
- @ComponetScan
즉, @SpringBootApplication 은 위 3가지 어노테이션을 각각 작성하는 것과 동일하게 작동함을 확인 할 수 있습니다.
실제로 그런지 궁금하신분은 아래의 코드대로 실행해보시면 정상 동작함을 확인 할 수 있습니다.
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@ComponentScan.Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @ComponentScan.Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
public class TestApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(TestApplication.class, args);
}
}
그럼 각각의 어노테이션의 역할에 대해 알아보겠습니다.
@SpringBootConfiguration
@SpringBootConfiguration은 @Configuration의 하위 어노테이션으로 @Configuration과 동일한 역할을 수행합니다.
실제로 @SpringBootConfiguration 의 코드를 살펴보면 @Configuration 외에 별다른 것이 없다는 것을 확인 할 수 있습니다.
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
@AliasFor(
annotation = Configuration.class
)
boolean proxyBeanMethods() default true;
}
@SpringBootConfiguration 어노테이션은 애플리케이션에 1개만 존재해야 하며, 일반적으로 @SpringBootApplicaiton안에 포함 되어 있으므로 따로 작성할 필요는 없습니다. 해당 어노테이션이 불필요해 보임에도 불구하고 존재하는 이유는 해당 어노테이션을 기준으로 설정들을 불러오기 위함입니다. 대표적으로 SpringBoot가 제공하는 통합 테스트 어노테이션인 @SpringBootTest 는 이를 사용합니다.
@SpringBootTest는 테스트 설정을 위해 먼저 @SpringBootConfiguration을 가진 클래스를 찾고 찾은 클래스를 중심으로 하위에서 설정들을 자동으로 찾습니다. 일반적으로 @SpringBootConfiguration은 @SpringBootApplication 안에 포함되어 있으므로 메인 클래스가 찾아집니다.
@EnableAutoConfiguration
@EnableAutoConfituration은 사전에 정의한 라이브러리들을 Bean으로 등록해주는 어노테이션입니다.
사전에 정의한 라이브러리들 모두 등록되는 것은 아니고 특정 조건이 만족될 경우에 Bean으로 등록합니다.
@ComponentScan
@ComponetScan은 @component 어노테이션 및 @Service, @Repository, @Controller 등의 어노테이션을 스캔하여 Bean으로 등록해주는 어노테이션입니다.
'Dev > Spring & Spring Boot' 카테고리의 다른 글
| Servlet & Servlet Container (0) | 2022.11.13 |
|---|---|
| [Spring] IoC,DI 란? (0) | 2022.11.05 |