-
IoC 컨테이너와 빈(2) - 빈의 스코프카테고리 없음 2020. 3. 16. 23:10반응형
빈의 스포크
싱글톤
애플리케이션 전반에 걸쳐서 해당 빈의 인스턴스가 1개뿐
@Service public class Proto { @Autowired private Single single; public Single getSingle() { return single; } public void setSingle(Single single) { this.single = single; } }
@Service public class Single{ }
@Controller public class HomeController { @Autowired Proto proto; @Autowired Single single; @RequestMapping(value = "/", method = RequestMethod.GET) public String home(Locale locale, Model model) { System.out.println(single); System.out.println(proto.getSingle()); System.out.println(single); return "home"; } }
위의 코드 실행 결과 프로토타입
매번 새로운 인스턴스를 만들어서 사용
- Request
- Session
- WebSocket
@Service @Scope("prototype") public class Proto { }
@Service public class Single{ }
@Controller public class HomeController { @Autowired ApplicationContext ctx; @RequestMapping(value = "/", method = RequestMethod.GET) public String home(Locale locale, Model model) { 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("single"); System.out.println(ctx.getBean(Single.class)); System.out.println(ctx.getBean(Single.class)); System.out.println(ctx.getBean(Single.class)); return "home"; } }
Single proto 차이 프로토타입 빈이 싱글톤 빈을 참조시
싱글 인스턴스는 매번 같은 인스턴스를 가져오기 때문에 아무 문제 없음
@Service @Scope("prototype") public class Proto { @Autowired Single single; }
싱글톤 빈이 프로토타입 빈을 참조하면?
프로토타입 빈이 업데이트가 되어야 되는데 업데이트가 안된다.
@Service @Scope("prototype") public class Proto { @Autowired Single single; } @Service public class Single{ @Autowired private Proto proto; public Proto getProto() { return proto; } }
@Controller public class HomeController { @Autowired ApplicationContext ctx; @RequestMapping(value = "/", method = RequestMethod.GET) public String home(Locale locale, Model model) { 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("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 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()); return "home"; } }
싱글톤 빈이 프로토타입 빈을 참조할 때 이유 및 해결 방안
- 아래 코드를 설명하면 class기반의 빈을 프록시를 감싸서 그 프록시 빈을 사용하게 해라라고 설정
- 직접 사용하게 된다면 매번 프록시를 바꿔줘야되는데 매번 바꿔줄 수 없기 때문에 proxy를 상속받는 클래스를 만들어서 사용
- CG라이브러리기반에 클래스를 상속받아 프록시를 만들게 한다.
- 다이나믹 프록시(JDK)는 인터페이스의 프록시밖에 만들지 못한다.
싱글톤 빈이 프로로타입 빈을 참조할 때 scodped-proxy
proxyMode = ScopedProxyMode.TARGET_CLASS
@Scope 어노테이션에 proxyMode 사용 - 백기선님이 추천함
// CG라이브러리를 상속받는 프록시 사용 @Component @Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS) public class Proto { } // 다이내믹 프록시 사용(JDK) @Component @Scope(value = "prototype", proxyMode = ScopedProxyMode.INTERFACES) public class Proto { }
Object-Provider
@Component @Scope(value = "prototype") public class Proto { } @Service public class Single{ @Autowired private ObjectProvider<Proto> proto; public Proto getProto() { return proto.getIfAvailable(); } } @Controller public class HomeController { @Autowired ApplicationContext ctx; @RequestMapping(value = "/", method = RequestMethod.GET) public String home(Locale locale, Model model) { 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("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 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()); return "home"; } }
반응형