일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 28 |
29 | 30 | 31 |
- cd
- kafka
- transactionaleventlistener
- Kubernetes
- offsetdatetime
- git
- API
- spring kafka
- topic생성
- QueryDSL
- ECS
- Entity
- producer
- AWS
- CodePipeline
- entity graph
- JPA
- bean
- CI
- mysql
- Kotlin
- Spring Data JPA
- centos7
- spring
- Streams
- Spring JPA
- consumer
- mirror maker2
- K8s
- PAGING
- Today
- Total
Yebali
Spring Boot의 Auto Configuration 본문
Auto Configuration이란?
Auto Configuration이란 Spring Boot가 자주 사용되는 수많은 Bean들을 자동으로 등록해 주는 기능을 말한다.
아래에서 어떻게 많은 Bean들을 자동으로 등록해 주는지 살펴보자
알게 모르게 동작하는 Auto Configuration
우리가 Spring Boot를 사용할 때, 등록한 적 없는 수많은 Bean들을 사용한다.
이런 동작은 'spring-boot-autoconfiguration' 의존성이 해주는데 'spring-boot-autoconfiguration'은
'spring-boot-starter-web'을 사용하면 자동으로 포함되는 의존성이다.
'spring-boot-autoconfiguration' 패키지 내부를 살펴보면
'autoconfigure'하위에 여러 가지 자동 설정을 위한 패키지와 파일들이 존재한다.
예시: JdbcTemplate
그 중 JdbcTemplateAutoConfiguration을 보면 JdbcTemplate에 대한 설정이 존재한다.
- @AutoConfiguration: 자동 구성을 사용하기 위한 애노테이션
- after: 자동 구성이 되는 순서를 지정하기 위한 부분으로, 'JdbcTemplate'는 'DataSource'가 필요하기 때문에 해당 빈을 등록하는 'DataSourceAutoConfiguration' 다음에 실행되도록 설정되어 있다.
- @ConditionalOnClass: IF문과 유사한 기능으로 해당 클래스들이 있는 경우에만 설정이 동작한다.
- @Import: 스프링에서 설정을 추가할 때 사용된다. (해당 설정들을 함께 사용하겠다는 의미)
그리고 'JdbcTemplateConfiguration'에서 'JdbcTemplate' Bean을 만들어 등록한다.
- @Configuration + @Bean: Spring Bean을 등록하기 위한 조합
- @ConditionalOnMissingBean: 해당 Bean이 없을 때에만 이 설정을 적용함. 직접 등록된 Bean이 있으면 자동 구성은 동작하지 않는다.
위와 같은 방법으로 우리가 자주 사용하는 대부분의 Bean들이 자동으로 등록된다.
@AutoConfiguration의 동작
그렇다면 @AutoConfiguration은 어떻게 동작하는 것일까?
ImportSelector
@AutoConfiguration의 동작 방식을 알려면 먼저 ImportSelector에 대해 알아야 한다.
우리가 설정 정보를 추가할 때 사용하는 @Import는 2가지 사용 방법이 있다.
- 정적인 방법: @Import(Class.class), 코드에 대상을 지정하는 방식.
- 동적인 방법: @Import('ImportSelector'), 프로그래밍을 통해 설정으로 사용할 대상을 동적으로 지정하는 방식.
Spring 개발자라면 정적인 방식은 많이 보았겠지만 ImportSelector를 사용하는 동적인 방식은 익숙하지 않을 수 있다.
ImportSeletor는 동적인 설정을 지원하기 위해 Spring이 제공하는 인터페이스 중 하나로 'String[] selectImports()'을 구현해
원하는 설정들을 동적으로 선택할 수 있도록 지원하는 기능이다.
public class HelloImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"hello.selector.HelloConfig"};
}
}
위와 같이 'ImportSelect'작성해 주면 동적으로 설정을 동적으로 사용 기능을 만들 수 있다.
Spring Boot 내에서의 @AutoConfiguration
@SpringBootApplication 애노테이션 내부에는 @EnableAutoConfigration을 사용하고 있으며,
@EnableAutoConfiguration 애노테이션 내부에는 @Import(AutoConfigurationImportSelctor.class)를 사용하고 있다.
AutoConfigurationImportSelctor
AutoConfigurationImportSelctor는 'DeferredImportSelector->ImportSelector'의 구현체로
Spring Boot에서 사용할 설정들을 가져오는 기능을 담당한다.
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware, ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
.
.
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader())
.getCandidates();
Assert.notEmpty(configurations,
"No auto configuration classes found in "
+ "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
.
.
}
public final class ImportCandidates implements Iterable<String> {
private static final String LOCATION = "META-INF/spring/%s.imports";
public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {
Assert.notNull(annotation, "'annotation' must not be null");
ClassLoader classLoaderToUse = decideClassloader(classLoader);
String location = String.format(LOCATION, annotation.getName());
Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);
List<String> importCandidates = new ArrayList<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
importCandidates.addAll(readCandidateConfigurations(url));
}
return new ImportCandidates(importCandidates);
}
}
구현된 코드를 살펴보면 '/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports'파일을 읽어 설정 정보들을 가져오는 기능을 한다.
실제로 'spring-boot-autoconfigure' 내부는 'org.springframework.boot.autoconfigure.AutoConfiguration.import s'가
존재하며 그 안에는 수많은 Configuration설정들이 있다.
즉, 자동으로 Bean들이 등록되는 과정을 정리하면 아래와 같다.
@SpringBootApplication -> @EnableAutoConfiguration -> @Import(AutoConfigurationImportSelctor.class)
-> 'org.springframework.boot.autoconfigure.AutoConfiguration.import s'파일에 있는 설정 정보들을 읽음
-> 설정 정보를 사용해 Bean을 등록함.
@AutoConfiguration
@ConditionalOnProperty(name = "memory", havingValue = "on")
public class MemoryAutoConfig {
@Bean
public MemoryController memoryController() {
return new MemoryController(memoryFinder());
}
@Bean
public MemoryFinder memoryFinder() {
return new MemoryFinder();
}
}
만약, Bean을 등록할 때 스프링의 Auto Configuration기능을 사용하고 싶다면
위와 같이 @AutoConfiguration 애노테이션을 사용하고
'src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.import s'에
직접 만든 @AutoConfiguration을 사용하는 Class를 명시해 주면 Auto Configuration대상으로 지정되어 자동으로 Bean이 등록된다.
'Spring' 카테고리의 다른 글
Spring Security + JWT 발급 (1) | 2024.11.06 |
---|---|
Spring Cloud Gateway 동적으로 Route 변경하기 (feat. spring cloud config) (0) | 2024.04.08 |
WebSocket 구현하기 feat.Spring (0) | 2023.02.10 |
Spring Collection 조회 성능 비교 (0) | 2022.12.25 |
[Spring] 테스트에서 Static 메소드 Mocking하기 (0) | 2022.09.24 |