| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- boj
- gpdb
- 코딩테스트
- 구현
- programmers
- Python
- 시뮬레이션
- Priority Queue
- Back tracking
- hash table
- django
- spring boot
- Algorithm
- CSV
- 코테
- JavaScript
- 모의SW역량테스트
- Vue.js
- GitHub
- 알고리즘
- Trie
- BFS
- Data Structure
- Bruth Force
- SWEA
- DFS
- aws
- Linked list
- SQL
- 알고리듬
- 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 |