본문 바로가기

web +a

싱글톤 컨테이너

이번 챕터는 머릿속에 잘 정리했기 때문에 여긴 메모만 아무렇게나 했다.

 


∨ 웹애플리케이션은 고객 요청이 끊임없이 들어옴

: 그때마다 새로운 객체를 생성하는건 좋지 X

: 트래픽↑면 메모리효율↓↓↓↓

∴ 싱글톤

더보기

예제

public class SingletonService {
    // static 영역에 객체 instance를 하나 생성해서 올려둔다.
    private static final SingletonService instance = new SingletonService();
    
    // 이 객체 인스턴스가 필요하면 오직 getInstance() 통해서만 조회 가능
    // 매번 같은 인스턴스 반환
    public static SingletonService getInstance() {
        return instance;
    }
    // 외부에서 new 생성 불가능하게 private 지정
    private SingletonService() {
    }

    public void logic() {
        System.out.println("싱글톤 객체 로직 호출");
    }
}

 

∨ Test

@Test
@DisplayName("싱글톤 패턴을 적용한 객체 사용")
void singletonServiceTest() {
    SingletonService singletonService1 = SingletonService.getInstance();
    SingletonService singletonService2 = SingletonService.getInstance();

    assertThat(singletonService1).isSameAs(singletonService2);
}

 

참고) 

@Test
@DisplayName("스프링 없는 순수한 DI 컨테이너")
void pureContainer() {
    AppConfig appConfig = new AppConfig();

    MemberService memberService1 = appConfig.memberService();
    MemberService memberService2 = appConfig.memberService();

    // mS1 != mS2
    assertThat(memberService1).isNotSameAs(memberService2);
}

 


∨ 스프링 컨테이너 쓰면 객체를 싱글톤으로 관리해줌!

: 이때 싱글톤패턴의 단점은 모두 제거됨

더보기

- 코드 지저분해짐

- 구체클래스 의존 - DIP위반 -> OCP위반

- Test 어려워짐

- 변경어려워짐

- private 생성자 -> 자식클래스 만들기 어렵

 

● 그런데 스프링 컨테이너를 이용하면

사실 안티패턴이기도 한 이러한 싱글톤 패턴의 단점을 모두 해결한 싱글톤을 사용가능하다는 거

 

∨ Test

더보기
@Test
@DisplayName("스프링 컨테이너와 싱글톤")
void springContainer() {
    ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
    MemberService memberService1 = ac.getBean("memberService", MemberService.class);
    MemberService memberService2 = ac.getBean("memberService", MemberService.class);

    assertThat(memberService1).isSameAs(memberService2);
}

 

∨ 스프링 컨테이너에서 싱글톤만 지원하는 건 아니다

그러나 거의 대부분 싱글톤으로 쓸 일만 있다고 한다.

99.9%라고 하셨다.

 

 


 

∨ 싱글톤 방식의 주의점

 

- 객체는 상태를 유지하게 설계하면 안된다 (stateful X)

- 무상태(stateless)로 설계해야 함 

- 가급적 읽기만 가능해야 함

- 필드 대신에 지역변수/파라미터/ThreadLocal등을 사용

- 스프링 빈 필드에 공유값을 설정하면 아쥬아쥬 큰 장애 발생 가능 주의

 


∨ @Configuration과 싱글톤

이 어노테이션이 싱글톤을 보장한다. 

 

▽ 쭉 보면 공부했던 게 생각날 것임

 

- AppConfig <- AppConfig@CGLIB

(바이트코드조작라이브러리, 스프링빈으로등록되는건새로만들어진상속받은클래스)

- 그래서 @Bean 메서드마다 : 빈존재하면리턴, 빈존재안하면생성

=> 그래서 repository print문이 1번만 출력되는 것을 볼 수 있었음

 

- @Configuration 안쓰면 그냥 클래스 AppConfig를 사용 & 싱글톤보장X

- @Bean을 빈으로 등록하기는 하지만 싱글톤X

- 고민할 것 없이 설정정보는 항상 @Configuration

 

 


 

끗끗

반응형
다른 블로그