prototype bean은 정말 항상 새로운 객체를 반환할까?
Bean Scope를 좀 살펴보다가 아래와 같은 테스트를 돌려보았다.
@Configuration
public class BeanScopeConfig {
@Bean
public AccountService accountService() {
AccountService accountService = new AccountService();
accountService.setAccountRepository(accountRepository());
return accountService;
}
@Bean
@Scope(scopeName = "prototype")
public AccountRepository accountRepository() {
return new AccountRepository();
}
}
public class AccountService {
private AccountRepository accountRepository;
public AccountRepository getAccountRepository() {
return accountRepository;
}
public AccountService setAccountRepository(AccountRepository accountRepository) {
this.accountRepository = accountRepository;
return this;
}
}
AccountService는 AccountRepository를 주입받으며, AccountRepository의 scope는 prototype이다.
DI 된 prototype bean 테스트
@Test
public void test() throws Exception {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanScopeConfig.class);
AccountService accountService1 = applicationContext.getBean(AccountService.class);
AccountService accountService2 = applicationContext.getBean(AccountService.class);
assertThat(accountService1.getAccountRepository()).isNotSameAs(accountService2.getAccountRepository());
}
그럼 이 테스트 코드는 통과 할까? 정답부터 말하면 통과하지 않는다.
나는 singleton bean에 주입되는 prototype bean은 항상 다른 객체를 주입받는다고 생각했다. 그런데 그렇지 않다. BeanScopeConfig 클래스에 AccountService @Bean 설정을 보면 accountRepository 메소드를 통해 주입받는다. 이건 같은 객체를 주입받는다는 뜻이다.
ApplicationContext에서 가져온 prototype bean 테스트
@Test
public void test1() throws Exception {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanScopeConfig.class);
AccountRepository accountRepository1 = applicationContext.getBean(AccountRepository.class);
AccountRepository accountRepository2 = applicationContext.getBean(AccountRepository.class);
assertThat(accountRepository1).isNotSameAs(accountRepository2);
}
위 테스트는 통과한다. Spring Container인 ApplicationContext에서 getBean 메소드를 통해 가져오는 prototype bean은 항상 다른 객체를 반환한다. 그렇다면 내가 의도한대로 singleton bean에 prototype bean 주입 시 항상 다른 객체가 반환되게 하는 방법은 없을까?
Bean Lifecycle
Bean Lifecycle 관련된 인터페이스는 많다. 다 그렇진 않지만 Aware가 suffix로 붙은 인터페이스가 대부분 Lifecycle 관련된 인터페이스다.
BeanFactoryAware
public interface BeanFactoryAware extends Aware {
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
ApplicationContextAware
public interface ApplicationContextAware extends Aware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
이번 글에서는 BeanFactoryAware로 예제를 설명해보겠다.
public class AccountService implements BeanFactoryAware {
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
public AccountRepository getAccountRepository() {
return beanFactory.getBean(AccountRepository.class);
}
public AccountService setAccountRepository(AccountRepository accountRepository) {
this.accountRepository = accountRepository;
return this;
}
}
BeanFactoryAware를 통해 getAccountRepository method 호출 시 getBean 메소드를 통해 항상 다른 객체를 반환하게 만들었다. 다시 test를 돌려보자. 정상적으로 돌아간다.
출처 : https://blog.woniper.net/339?category=699184
'Spring Framework > Spring boot' 카테고리의 다른 글
Spring Data REST #3 내부 동작 (0) | 2020.09.04 |
---|---|
Spring Data REST #2 동작 원리 (0) | 2020.09.04 |
Spring Data REST #1 Introduction (0) | 2020.09.04 |
Spring *Utils Classes 배끼기 (0) | 2020.09.04 |
Spring IoC Container를 까보자 #BeanFactory와 ApplicationContext (0) | 2020.09.04 |
Spring IoC Container를 까보자 #Bean을 어떻게 반환할까? (0) | 2020.09.04 |
Spring IoC Container를 까보자 #Bean 등록은 어떻게 될까? (0) | 2020.09.04 |
Autowired Generics (Generics Type 주입하기) (0) | 2020.09.03 |