빈의 스코프
스프링 빈의 범위에는 싱글톤(Singleton)과 프로토타입(Prototype)가 있다.
싱글톤 스코프는 스프링에서 별도의 설정을 하지 않은 경우 기본적으로 동작하는 방식으로 애플리케이션이 구동될 떄 하나의 인스턴스만 생성하고 여러번 호출 할때 매번 동일한 객체를 리턴한다.
반대로 프로토타입 스코프는 매번 새로운 인스턴스를 생성하여 매번 다른 객체를 리턴한다.
아래에 간단한 예시로 확인해보자.
@Component
public class Singleton {
}
@Component
@Scope("prototype")
public class Prototype {
}
이렇게 두 개의 클래스를 빈으로 등록을하는데 Protytype 클래스의 범위는 prototype으로 하였다. 이후 ApplicationContext에서 찍어보면 아래와 같은 결과를 확인할 수있다.
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ApplicationContext context;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(context.getBean(Singleton.class));
System.out.println(context.getBean(Singleton.class));
System.out.println(context.getBean(Prototype.class));
System.out.println(context.getBean(Prototype.class));
}
}
실행결과
com.giantdwarf.scope.Singleton@27b45ea //동일
com.giantdwarf.scope.Singleton@27b45ea
com.giantdwarf.scope.Prototype@3e17a0a1 //다름
com.giantdwarf.scope.Prototype@790a251b
서로다른 스코프의 빈 주입시 문제점
프로토타입 스코프의 빈이 싱글톤 스코프의 빈을 참조하는 경우
프로토타입 빈은 매번 꺼낼떄마다 새로운 인스턴스가 나오고 그 빈이 참조하는 싱글톤 스코프의 빈은 동일하다.(문제 없다)
@Component
@Scope("prototype")
public class Prototype {
@Autowired
Singleton singleton;
}
싱글톤 스코프의 빈이 프로토타입의 빈을 참조하는 경우
싱글톤 스코프의 빈은 인스턴스가 생성될 때 주입받아 세팅이 되서 프로토타입의 빈이지만 의도한대로 다른 인스턴스를 주지않고 같은 인스턴스가 나오게된다.
@Component
public class Singleton {
@Autowired
private Prototype prototype;
public Prototype getPrototype() {
return prototype;
}
}
@Component
public class AppRunner implements ApplicationRunner {
@Autowired
ApplicationContext context;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(context.getBean(Singleton.class).getPrototype());
System.out.println(context.getBean(Singleton.class).getPrototype());
}
}
실행결과
com.giantdwarf.scope.Prototype@1416cf9f
com.giantdwarf.scope.Prototype@1416cf9f
이 문제에서처럼 싱글톤 스코프가 프로토타입의 스코프를 직접 참조하면 안되기 때문에 기존의 빈을 프록시로 감싸고 감싼 프록시를 주입하여 사용하면 된다.
@Component
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class Prototype {
}
실행결과
com.giantdwarf.scope.Prototype@3c0bbc9f
com.giantdwarf.scope.Prototype@1317b708
NO, INTERFACES, TARGET_CLASS가 존재하며 기본값은 NO이다.
INTERFACES의 경우는 JDK dynamic proxy를 사용해서 인터페이스 기반의 프록시를 생성한다.
TARGET_CLASS는 스프링 프레임워크에 내장된 CGLIB를 사용하여 클래스도 클래스 기반의 다이나믹 프록시를 생성한다.
'프로그래밍 > Spring' 카테고리의 다른 글
스프링 부트의 오류처리(Error Handling) (0) | 2020.07.05 |
---|---|
스프링부트의 자동설정 (0) | 2020.06.21 |
스프링 AOP (0) | 2020.04.19 |
애노테이션(Annotation을 이용한 의존객체 주입 (0) | 2020.03.15 |
제어 역전(IoC)와 의존성주입(DI) (0) | 2020.03.12 |