스코프
싱글톤 - Application 전반에 걸쳐서 해당 Bean의 인스턴스가 오직 한 개뿐
Single은 Proto를 주입받는다.
@Component
public class Single {
@Autowired
Proto proto;
public Proto getProto() {
return proto;
}
}
System.out.println(proto); : AppRunner의 Proto
System.out.println(single.getProto()); : Single의 Proto
public class AppRunner implements ApplicationRunner {
@Autowired
Single single;
@Autowired
Proto proto;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(single);
System.out.println(proto);
System.out.println(single.getProto());
}
}
실행결과 각각의 프로토가 같은 해시 코드인 것을 확인할 수 있다.
프로토타입 - 매번 새로운 인스턴스를 만들어서 사용하는 scope
Scope prototype으로 지정
@Component @Scope("prototype")
public class Proto {
}
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ApplicationContext ctx;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("single");
System.out.println(ctx.getBean(Single.class));
System.out.println(ctx.getBean(Single.class));
System.out.println(ctx.getBean(Single.class));
System.out.println("proto");
System.out.println(ctx.getBean(Proto.class));
System.out.println(ctx.getBean(Proto.class));
System.out.println(ctx.getBean(Proto.class));
}
}
prototype은 각각의 다른 해시 코드가 출력된다.
Prototype의 Scope 이 Singletontype의 Scope을 사용하는 경우
- 아무 문제가 없다
- Prototype의 Scope 매번 다른 인스턴스를 생성하지만 Singletontype의 Scope은 하나의 인스턴스를 참조하기 때문에 상관없다.
@Component @Scope("prototype")
public class Proto {
@Autowired
Single single;
}
Singletontype의 Scope이 Prototype의 Scope을 사용하는 경우
@Component
public class Single {
@Autowired
Proto proto;
public Proto getProto() {
return proto;
}
}
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ApplicationContext ctx;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("single");
System.out.println(ctx.getBean(Single.class));
System.out.println(ctx.getBean(Single.class));
System.out.println(ctx.getBean(Single.class));
System.out.println("proto");
System.out.println(ctx.getBean(Proto.class));
System.out.println(ctx.getBean(Proto.class));
System.out.println(ctx.getBean(Proto.class));
System.out.println("proto by single");
System.out.println(ctx.getBean(Single.class).getProto());
System.out.println(ctx.getBean(Single.class).getProto());
System.out.println(ctx.getBean(Single.class).getProto());
}
}
Prototype의 해시 코드가 의도와는 다르게 바뀌지 않는다.
해결방법 1. ProxyMode의 사용
프락시로 Proto를 감싸는 이유는
Single이 Proto 타입의 빈을 직접 참조하면 안 되기 때문에
직접 참조해버리면 Proto는 매번 같은 인스턴스를 가지므로
Proxy로 감싸버린다. (with cglib)
https://jwdeveloper.tistory.com/47?category=823919
@Component @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Proto {
}
Proxy 인스턴스가 Bean으로 등록
해당 Proxy Bean을
@Autowired
Proto proto;
에 주입 (타입이 같기 때문에 주입이 가능하다.)
https://en.wikipedia.org/wiki/Proxy_pattern
해결방법 2.ObjectProvider의 사용
@Component
public class Single {
@Autowired
private ObjectProvider<Proto> proto;
public Proto getProto() {
return proto.getIfAvailable();
}
}
코드참조
https://github.com/mike6321/Spring/tree/master/Spring/demospring51
'Spring > Spring' 카테고리의 다른 글
(SPRING) Spring ApplicationContext의 내부 (1) (1) | 2020.03.01 |
---|---|
(SPRING) IoC 컨테이너 - Environment_프로파일 (0) | 2020.02.14 |
(SPRING) IoC 컨테이너 - @Component와 컴포넌트 스캔 (0) | 2020.01.01 |
(SPRING) IoC 컨테이너 - @Autowired (2) | 2020.01.01 |
(SPRING) IoC 컨테이너 - ApplicationContext와다양한 빈 설정 방법 (0) | 2020.01.01 |