클래스의 인스턴스가 1개만 생성되는 것을 보장하는 디자인 패턴
싱글톤 패턴 사용 이유
요청 시마다 객체를 새로 할당해야 함 -> 메모리 낭비 심하다
싱글톤 설계 예시
public class SingletonService {
private static final SingletonService instance = new SingletonService();
public static SingletonService getInstance(){
return instance;
}
private SingletonService(){
}
public void logic(){
System.out.println("싱글톤 객체 호출");
}
}
순수 자바로 구현한 싱글톤 패턴의 문제점
스프링 컨테이너는 자동으로 싱글톤 컨테이너로 관리해 위와 같은 문제점을 해결해준다.
싱글톤 방식의 주의점
하지만 객체(인스턴스)를 공유하기 때문에 싱글톤 객체는 상태를 유지하게 설계하면 안된다!
→ ex) A가 10000원 넣고, B가 20000원 넣었을 때 A가 20000원을 사용하게 됨
따라서 무상태(stateless)로 설계해야 한다.
@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() {
System.out.println("memberRepository!!");
return new MemoryMemberRepository();
}
@Bean
public DiscountPolicy discountPolicy() {
return new FixDiscountPolicy();
}
}
다음과 같은 코드가 있을 때 스프링은 @Bean이 붙은 메서드를 스프링 빈으로 등록한다.
이 때 memberRepository는 memberService에서 한 번, orderService에서 두 번, memberRepository에서 세 번 호출된다.
하지만 실제로 실행해 보면 memberRepository!!
는 한 번 출력되는데 이는 스프링 컨테이너가 싱글톤으로 관리되고 있음을 의미한다.
그리고 그 역할은 @Configuration이 수행해준다.
AppConfig라는 클래스를 스프링 컨테이너에 등록할 때 AppConfig를 상속받은 다른 클래스를 만들고 그 클래스를 스프링 빈에 등록한다.
-> 만약 @Configuration을 제외하고 위 코드를 실행 시키면 memberRepository!!가 3번 실행됨
@Configuration 정리
@Configuration을 붙이면 해당 클래스를 상속받은 임의의 다른 클래스를 만들고 스프링 빈으로 등록한다. 따라서 이미 스프링 빈에 등록된 객체를 호출하면 기존에 등록된 빈 instance를 반환한다.