싱글톤 패턴
- 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴
- 그래서 객체 인스턴스를 2개 이상 생성하지 못하도록 막아야 한다
- private 생성자를 사용해서 외부에서 임의로 new 키워드를 사용하지 못하도록 막아야 한다
package hello.core.singleton;
public class SingletonService {
private static final SingletonService instance = new SingletonService();
private SingletonService() {
}
public static SingletonService getInstance() {
return instance;
}
public void logic() {
System.out.println("called singleton");
}
}
- 프로젝트 구동시 최초 1회 생성
- getInstance()메서드를 통해서만 조회가능하다. 이 메서드를 호출하면 항상 같은 인스턴스만 반환
- 기본 생성자를 private로 만들어서 외부에서 해당 객체 인스턴스가 생성되는것을 막는다
@Test
@DisplayName("싱글톤 패턴을 적용한 객체 사용")
void singletonService() {
SingletonService instance1 = SingletonService.getInstance();
SingletonService instance2 = SingletonService.getInstance();
System.out.println("instance1 = " + instance1);
System.out.println("instance2 = " + instance2);
assertThat(instance1).isSameAs(instance2);
}
- 호출할 때마다 같은 객체 인스턴스를 반환한다.
싱글톤 패턴의 문제점
- 싱글톤 패턴을 적용하기 위한 코드양이 많아진다.
- 의존관계상 클라이언트가 구체 클래스에 의존 -> DIP를 위반한다.
- DIP를 위반하므로 OCP를 위반할 가능성이 높아진다.
- 테스트하기 어려워진다
- 내부 속성을 변경하거나 초기화가 어렵다.
- private 생성자로 자식 클래스를 만들기 어렵다
- 유연성이 떨어진다
- 안티패턴으로 불리기도 한다
싱글톤 컨테이너
스프링 컨테이너는 스프링의 단점을 해결하면서 객체 인스턴스를 싱글톤으로 관리한다
- 스프링 컨테이너는 싱글톤 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리
- 컨테이너는 객체를 하나만 생성하여 관리
- 스프링 컨테이너를 싱글톤 역할을 한다. 이처럼 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라 한다.
- 스프링 컨테이너의 이런 기능 덕분에 싱글턴 패턴의 모든 단점을 해결하면서 객체를 싱글톤으로 유지할 수 있다.
- 싱글톤 패턴을 위한 지저분한 코드가 들어가지 않아도 된다.
- DIP, OCP, 테스트, private 생성자로부터 자유롭게 싱글톤을 사용할 수 있다
@Test
@DisplayName("스프링 컨테이너와 싱글톤")
void springContainer() {
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService1 = ac.getBean("memberService", MemberService.class);
MemberService memberService2 = ac.getBean("memberService", MemberService.class);
//3. 참조값 확인
System.out.println("memberService1 = " + memberService1);
System.out.println("memberService2 = " + memberService2);
//memberService != memberService2
assertThat(memberService1).isSameAs(memberService2);
}
싱글톤 방식의 주의점
- 객체 인스턴스를 하나만 생성해서 사용하는 싱글톤 방식은 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에 싱글톤 객체는 상태를 유지(Stateful)하게 설계하면 안된다
- 무상태(Stateless)로 설계해야한다!
- 특정 클라이언트에 의존적인 필드가 있으면 안된다
- 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다
- 가급적 읽기만 가능하도록 해야한다
- 필드 대신에 자바에서 공유되지 않는, 지역변수, 파라미터, ThreadLocal 등을 사용해야 한다.
Reference
스프링 핵심 원리 - 기본편 - 인프런 | 강의
스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런
www.inflearn.com
'Spring' 카테고리의 다른 글
Spring - 의존 관계 자동 주입 (0) | 2023.04.19 |
---|---|
Spring - 컴포넌트 스캔 (0) | 2023.04.14 |
Spring - BeanFactory와 ApplicationContext (0) | 2023.04.08 |
Spring - 스프링 컨테이너 (0) | 2023.04.07 |
Spring - 컨테이너와 IOC/DI (0) | 2023.03.24 |