Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- java
- Android
- JPQL
- Exception
- 김영한
- Proxy
- AOP
- 그리디
- springdatajpa
- 스프링 핵심 기능
- 인프런
- QueryDSL
- 스프링 핵심 원리
- Spring Boot
- SpringBoot
- 알고리즘
- http
- transaction
- Servlet
- spring
- 백준
- db
- Greedy
- 스프링
- Thymeleaf
- 자바
- kotlin
- jpa
- pointcut
- JDBC
Archives
- Today
- Total
개발자되기 프로젝트
프로토타입 빈과 싱글톤 빈을 같이 사용하면? 본문
- 프로토타입 빈은 스프링 컨테이너에 요청할 때 마다 새로운 인스턴스 생성하여 반환함.
- 그런데 싱글톤 빈과 같이 사용하면 의도치 않은 동작을 한다.
1. 프로토타입 빈 직접 요청
- 어떤 protoType Bean이 있다고 하자.
- 해당 클래스에는 addCound method를 제공한다.
- 만약 A client가 prototypeBean을 요청하고 prototypeBean1이라는 이름으로 받으려고 한다.
- 스프링 컨테이너는 인스턴스를 새로 생성해서 반환한다(prototypeBean1, @x01)
- 그리고 client A는 addcount를 실행한다.ㄷ
- protypeBean.getCount를 하면 1이 리턴된다.
- 이 때 Client B도 prototypeBean을 요청하고 prototypeBean2라는 이름으로 받으려고 한다.
- 스프링 컨테이너는 인스턴스를 새로 생성해서 반환한다.(prototypeBean2, @x02)
- client B는 addcount를 실행한다.
- prototypeBean2.getCount를 실행하면 1이 리턴될 것이다.
-
public class SingletonWithPrototypeTest1 { @Test public void prototypeFind(){ AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class); PrototypeBean prototypeBean1 = ac.getBean(PrototypeBean.class); prototypeBean1.addCount(); Assertions.assertThat(prototypeBean1.getCount()).isEqualTo(1); PrototypeBean prototypeBean2 = ac.getBean(PrototypeBean.class); prototypeBean2.addCount(); Assertions.assertThat(prototypeBean2.getCount()).isEqualTo(1); } @Component @Scope("prototype") static class PrototypeBean{ private int count = 0; public void addCount(){ count++; } public int getCount(){ return count; } @PostConstruct public void init(){ System.out.println("PrototypeBean.init" + this); } @PreDestroy public void destroy(){ System.out.println("PrototypeBean.destroy"); } } }
2. 싱글톤 빈에서 프로토타입 빈 사용?
- clientBean이라는 싱글톤 빈이 의존관계 주입을 통해서 프로토타입 빈을 주입받는다고 해보자.
- client는 싱글톤이다. 스프링 컨테이너 생성 시점에 함께 생성, 의존관계 주입 받음
- clientBean은 자동 의존관계 주입을 사용하는데, 주입 시점에 프토토타입 빈을 요청함.
- 스프링 컨테이너는 prototypeBean을 생성해서 clientBean에 return함. 이 때 count = 0
- 그러면 clientBean은 프로토타입 빈은 내부 필드에 prototypeBean의 참조값을 보관.
- clientBean은 싱글톤이기 때문에 항상 같은 인스턴스를 반환한다.
- clientA, clientB가 clientBean을 요청하면 이에 해당하는 prototypeBean은 항상 @x01이 리턴될듯?
- client A가 clientBean의 로직을 호출한다.
- 해당 로직은 clientBean와 의존관계에 있는 prototypeBean의 count를 증가시킨다.
- 이번엔 client B가 clientBean을 받는다. 싱글톤이기 때문에 같은 인스턴스를 받는다.
- 이 때! 위에서 예상한 것과 같이 prototypeBean은 이미 clientBean생성시 주입이 끝났다.
- 즉 싱글톤 내부에 있는 prototypeBean은 한번 주입된 후에 바뀌지 않는다.
- 좀더 풀어 설명하면 처음 싱글톤 빈(client bean)생성시 싱글톤 빈이 스프링 컨테이너에 프로토타입 빈 요청!
- 이후 다른 클라이언트가 싱글톤 빈을 요청할 때는 이미 프로토타입빈의 주입이 완료되었음.
- 싱글톤에 DI가 완료된 후 스프링 컨테이너에 프로토타입 빈을 요청할 일이 없다.
- 즉 한마디로 싱글톤 빈은 항상 같은 인스턴스를 반환한다!
3.Test
public class SingletonWithPrototypeTest1 {
@Test
public void prototypeFind(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PrototypeBean.class);
PrototypeBean prototypeBean1 = ac.getBean(PrototypeBean.class);
prototypeBean1.addCount();
Assertions.assertThat(prototypeBean1.getCount()).isEqualTo(1);
PrototypeBean prototypeBean2 = ac.getBean(PrototypeBean.class);
prototypeBean2.addCount();
Assertions.assertThat(prototypeBean2.getCount()).isEqualTo(1);
}
@Test
void singletonClientPrototype(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(ClientBean.class, PrototypeBean.class);
ClientBean clientBean1 = ac.getBean(ClientBean.class);
int count1 = clientBean1.logic();
Assertions.assertThat(count1).isEqualTo(1);
ClientBean clientBean2 = ac.getBean(ClientBean.class);
int count2 = clientBean2.logic();
Assertions.assertThat(count2).isEqualTo(2);
}
@Component
@Scope("singleton")
static class ClientBean{
private final PrototypeBean prototypeBean;
@Autowired
public ClientBean(PrototypeBean prototypeBean) {
this.prototypeBean = prototypeBean;
}
public int logic(){
prototypeBean.addCount();
return prototypeBean.getCount();
}
}
@Component
@Scope("prototype")
static class PrototypeBean{
private int count = 0;
public void addCount(){
count++;
}
public int getCount(){
return count;
}
@PostConstruct
public void init(){
System.out.println("PrototypeBean.init" + this);
}
@PreDestroy
public void destroy(){
System.out.println("PrototypeBean.destroy");
}
}
}
흠.. 프로토타입 빈을 매번 새로 생성하고싶은데...싱글톤 내부에서 사용하면 매 번 생성하지 못한다. 의도가 아니야
도움!
4. GitHub : 210730 singletonBean에서 prototypeBean 사용
'인프런 > [인프런] Spring 핵심원리 이해' 카테고리의 다른 글
웹 스코프, provider (0) | 2021.08.01 |
---|---|
Provider, ObjectProvider (0) | 2021.08.01 |
빈 스코프?? (0) | 2021.07.30 |
@PostConstruct, @PreDestroy (0) | 2021.07.30 |
빈 생명주기 : @Bean(initMethod, destroyMethod) (0) | 2021.07.30 |
Comments