Bean의 Scope
Scope
Singleton
- Application 전반에 걸쳐서 해당 Bean의 Instance가 오직 하나 뿐인 것.
Prototype
- Bean을 주입할 때 마다 새로운 Bean을 생성해서 주입.
Prototype Bean이 Singleton Bean을 참조하면
아무 문제가 없다.
매번 새로운 ProtoType Bean이 가지고 있는 Singleton Bean은 매번 동일하다.
Singleton Bean이 ProtoType Bean을 참조하면
Proto.java
@Component @Scope("prototype")
public class Proto {
}
Single.java
@Component
public class Single {
@Autowired
Proto proto;
public Proto getProto() {
return proto;
}
}
AppRunner.java
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ApplicationContext ctx;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("single.get");
System.out.println(single.getProto());
System.out.println(single.getProto());
System.out.println(single.getProto());
}
}
위와 같은 코드의 결과는 아래와 같다.
proto by single
com.springstudy.beandemo.Proto@1804f60d
com.springstudy.beandemo.Proto@1804f60d
com.springstudy.beandemo.Proto@1804f60d
Singleton Bean이 가지고 있는 Prototype의 bean을 호출하였는데 매번 동일한 Bean이 호출되었다.
위와 같은 상황을 해결하기 위한 방법들
1. proxyMode를 설정
- ScopedProxyMode.DEFAULT
- Proxy를 사용하지 않는다는 뜻.
- ScopedProxyMode.TARGET_CLASS
- CGLIB의 Dynamic Proxy가 적용된다.
- Target Class를 Proxy로 감싸달라는 뜻
- 다른 Bean들이 해당 Bean을 사용할 때 이 Bean을 감싼 Proxy Bean을 사용하게 해라.
- Proxy Patturn 참조
- 해당 Bean을 상속받은 Proxy Instance가 만들어 지고 그 Instance가 Bean으로 등록된다. 그 후 등록된 Bean을 주입해 준다.
왜 Proxy를 거쳐야 하나 ??
- 직접 참조하면 Bean을 바꿔줄 수 없다.
따라서 Proto 를 아래와 같이 수정하면 된다.
Proto.java
@Component @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Proto {
}
2. ObjectProvider 사용
Single에서 ObjectProvider를 사용하여 해결할 수 있다.
Single.java
@Component
public class Single {
@Autowired
ObjectProvider<Proto> proto;
public Proto getProto() {
return proto.getIfAvailable();
}
}
Bean 선언 부분이 아닌 곳에 Spring Code가 삽입되므로 추천하고싶은 방법은 아니다.
Singleton 사용시 주의할 점
1. Property가 공유된다. (Thread safe 하지 않다)
2. Application Context 초기 구동시 생성된다.
- Application 구동 시간이 조금 더 걸릴 수 있다.
Project Repository
- https://github.com/Seongmun-Hong/SpringStudy
Reference
- https://www.inflearn.com/course/spring-framework_core