일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- hash table
- SWEA
- SQL
- boj
- aws
- 코딩테스트
- django
- Algorithm
- JavaScript
- GitHub
- 시뮬레이션
- Vue.js
- DFS
- spring boot
- Data Structure
- Linked list
- programmers
- gpdb
- 알고리듬
- 알고리즘
- 구현
- BFS
- Trie
- 모의SW역량테스트
- Back tracking
- CSV
- 코테
- Python
- Bruth Force
- Priority Queue
- Today
- Total
hotamul의 개발 이야기
Configuration, proxyBeanMethods 본문
@Configuration
annotation은 @Component
라는 meta annotation으로 만들어진 composed annotation이다. (Meta Annotation, Composed Annotation)
하지만 @Component
와는 다른 점이 바로 proxyBeanMethods
라는 것이다.
proxyBeanMethods = false
기본적으로 @Configuration
annotation의 proxyBeanMethods
는 true
이다. 그럼 proxyBeanMethods
가 false
일 때와 true
일 때와 뭐가 다른 걸까?
@Configuration
annotation에 대해 이해하기 위해 아래와 같은 테스트 코드를 만들어봤다.
public class ConfigurationTest {
@Test
void configuration() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.register(MyConfig.class);
ac.refresh();
Bean1 bean1 = ac.getBean(Bean1.class);
Bean2 bean2 = ac.getBean(Bean2.class);
Assertions.assertThat(bean1.common).isSameAs(bean2.common);
}
@Configuration
static class MyConfig {
@Bean
Common common() {
return new Common();
}
@Bean
Bean1 bean1() {
return new Bean1(common());
}
@Bean
Bean2 bean2() {
return new Bean2(common());
}
}
static class Bean1 {
private final Common common;
Bean1(Common common) {
this.common = common;
}
}
static class Bean2 {
private final Common common;
Bean2(Common common) {
this.common = common;
}
}
static class Common {
}
}
Java 코드로만 보자면 위 코드의 MyConfig
클래스는 bean1()
, bean2()
메소드가 호출되면 새로운 Common
객체를 생성하는 것으로 보인다. (return new Bean1(common())
)
하지만 아래 테스트 코드를 실행하면 테스트가 성공하는 것을 확인할 수 있다.
@Test
void configuration() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.register(MyConfig.class);
ac.refresh();
Bean1 bean1 = ac.getBean(Bean1.class);
Bean2 bean2 = ac.getBean(Bean2.class);
Assertions.assertThat(bean1.common).isSameAs(bean2.common);
}
위 테스트 결과는 factory method를 이용해서 object를 생성하는 코드를 여러 번 호출하더라도 딱 한 개의 object만 사용하고 있다는 것을 말해준다. 어떻게 된 일일까?
java 코드상으로만 보면 하나의 Bean(Common
)을 두 개 이상의 다른 Bean(Bean1
, Bean2
)에서 의존할 때 factory method(common()
)로 호출하게 되면 새로운 Bean이 만들어져야 할 것 같다.
Spring Container에서 관리되는 Bean은 기본적으로 singleton이다. Spring의 기본적인 동작 방식(Bean을 Singleton으로 관리)을 java 코드로도 가능하게 하려다 보니 Proxy를 만들어서 이러한 Singleton 방식을 유지하고 있는 것이다.
간단하게 @Configuration
annotation이 선언된 클래스가 동작하는 과정을 아래 코드에서 확인해 볼 수 있다.
static class MyConfigProxy extends MyConfig {
private Common common;
@Override
Common common() {
if (this.common == null) this.common = super.common();
return this.common;
}
}
즉 @Configuration
annotation을 선언하면 기본적으로 MyConfigProxy
클래스처럼 생성한 객체를 캐싱해서 return
한다.
Spring 5.2에서부터 이러한 proxy 방식을 off 할 수 있게 되었는데 이것이 proxyBeanMethods = false
이다. 즉 @Configuration(proxyBeanMethods=false)
를 사용한다는 것은 @Component
annotation을 사용하는 것과 동일하다.
// @Configuration(proxyBeanMethods=false)
@Component
static class MyConfig {
@Bean
Common common() {
return new Common();
}
@Bean
Bean1 bean1() {
return new Bean1(common());
}
@Bean
Bean2 bean2() {
return new Bean2(common());
}
}
(@Component
가 선언된 MyConfig
클래스는 @Configuration(proxyBeanMethods=false)
가 선언된 것과 동일하게 동작한다)
Spring에서 proxyBeanMethods=false
사용하는 예시
EnableScheduling
annotation을 보면 SchedulingConfiguration
을 import 하는 것을 볼 수 있는데 이때 SchedulingConfiguration
클래스에 @Confugration
annotation이 proxyBeanMethods=false
로 선언되어 있는 것을 확인할 수 있다.
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class SchedulingConfiguration {
@Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {
return new ScheduledAnnotationBeanPostProcessor();
}
}
해당 포스트는 토비의 스프링 부트 - 이해와 원리 강의 중 "@Configuration과 proxyBeanMethods" 내용을 정리한 글입니다.
'Dev. > Spring-Boot' 카테고리의 다른 글
Meta Annotation, Composed Annotation (0) | 2023.09.05 |
---|---|
Spring Boot는 왜 jar 파일로 실행 가능할까 (0) | 2023.09.02 |
Spring Boot가 뭔데? (0) | 2023.08.15 |
[Spring-Boot] 환경 변수 저장 및 사용 방법 (0) | 2023.02.17 |