싱글톤 패턴을 사용하는 이유
대부분의 Spring 애플리케이션은 웹 애플리케이션입니다.
웹 애플리케이션은 아래와 같이 여러 클라이언트로부터 동시에 요청을 받는 경우가 많습니다.
이때 여러 클라이언트에서 동시에 요청이 들어오면 클라이언트별로 필요한 객체를 생성해야 하므로 메모리가 낭비된다.
싱글톤 패턴은 이 현상, 즉 각 클라이언트에 대한 새 개체 생성으로 인한 메모리 낭비를 해결할 수 있습니다.
싱글톤 패턴
앞서 언급했듯이 Singleton 패턴 핸들은 각 클라이언트에 대한 객체를 생성하는 대신 클래스의 인스턴스를 생성하여 모든 클라이언트에 대해 작동합니다.
싱글톤을 만드는 방법은 여러 가지가 있지만 그 중 하나는 미리 객체를 만들어 정적인 공간에 두는 것입니다.
싱글톤 패턴을 사용해 봅시다.
private생성자가 있는 모든 외부 new키워드 사용을 방지합니다.
private static final SingletonService instance = new SingletonService();
//객체 인스턴스를 조회할수있게 하는 메서드
public static SingletonService getInstance() {
return instance;
}
또한 static기존에 생성한 오브젝트를 해당 영역에 배치하는 방식을 사용합니다.
이렇게 생성된 객체는 클라이언트로부터 요청이 올 때마다 새 객체를 생성하는 대신 기존 객체를 사용합니다.
그러나 이렇게 생성된 클라이언트에는 여러 가지 문제점이 있다. 클라이언트는 구체적인 클래스에 의존하기 때문에 DIP를 위반하므로 아마도 OCP와 생성자 private이러한 이유로 자식 클래스를 생성하기가 어렵습니다. 이 문제를 해결하기 위해 싱글톤 컨테이너가 나왔다.
싱글톤 컨테이너
싱글톤 컨테이너를 사용하면 위에서 언급한 싱글톤의 단점을 상쇄할 수 있습니다.
Spring Container는 싱글톤 컨테이너 역할을 하므로 빈을 등록할 때 싱글톤 방식을 사용한다.
ApplicationContext ac = newAnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService1 = ac.getBean("memberService",MemberService.class);
MemberService memberService2 = ac.getBean("memberService",MemberService.class);
마지막으로 위 코드에서 memberService1과 memberService2는 동일한 객체를 공유합니다.
주의
Spring Container를 사용할 때 memberService1과 memberService2는 위와 같은 객체를 공유한다.
이때 회원서비스 개인 가격; 다음과 같은 상태를 포함하는 필드가 있다고 가정합니다.
이때 memberService1과 memberService2는 서로 다른 값이 설정되어 있다고 가정하자.그러나 memberService1과 memberService2는 동일한 객체를 공유하므로 각 객체에 다른 값을 할당할 수 없습니다. 따라서 Singleton 패턴을 사용할 때는 Stateless 상태로 설계해야 합니다.
CGLIB
Spring 컨테이너는 싱글톤 레지스트리입니다. -> 스프링 빈이 싱글톤인지 확인합니다.
이 경우 bean이 싱글톤인지 확인하는 것이 중요합니다. @Configuration 오전.
@Configuration
public class AppConfig {
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
@Bean
public OrderService orderService() {
return new OrderServiceImpl(
memberRepository(),
discountPolicy());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
...
}
AppConfig 클래스의 메소드를 통해 bean으로 등록을 시도할 때, @Configuration Spring을 사용한다면 이렇게 할 것입니다. CGLIB(Bytecode Manipulation Library)는 각 빈의 싱글톤을 보장합니다.
CGLIB싱글톤을 보장하는 이유
AppConfig 코드 고려 memberService(),orderService() 어떤 방법 memberRepository()call be see 즉, 싱글톤이 깨진 것처럼(new MemoryMemberRepository(); 2 호출됨) 그러나 Spring은 이러한 문제를 해결합니다. CGLIB에 의해 해결
CGLIB위 이미지와 같이 AppConfig@CGLIB라는 클래스를 생성합니다. AppConfig@CGLIB 클래스를 사용하면 각 빈이 싱글톤을 보장할 수 있습니다.
따라서 Spring은 각 빈의 싱글톤을 보장하기 위해 CGLIB를 사용하며 CGLIB를 사용하려면 @Configuration을 사용해야 한다.
