Spring 없이 순수 DI 컨테이너 테스트
public class SingletonTest {
@Test
@DisplayName("스프링 없는 순수한 DI 컨테이너")
void pureContainer(){
AppConfig appConfig = new AppConfig();
// 1.조회 : 호출할 때 마다 객체를 생성
MemberService memberService1 = appConfig.memberService();
// 2.조회 : 호출할 때 마다 객체를 생성
MemberService memberService2 = appConfig.memberService();
//참조값이 다른것을 확인
System.out.println("memberService1 = " + memberService1);
System.out.println("memberService2 = " + memberService2);
Assertions.assertThat(memberService1).isNotSameAs(memberService2);
}
}
결과
memberService1 = hello.core.member.MemberServiceImpl@275710fc
memberService2 = hello.core.member.MemberServiceImpl@525f1e4e
- Spring이 없는 순수한 DI 컨테이너로서 AppConfig는 각 요청에 대해 새 객체를 생성합니다.
- 고객 트래픽이 초당 100에 도달하면 초당 100개의 객체가 생성되고 삭제됩니다.
=> 낭비되는 메모리가 많습니다. - 해결책은 하나의 객체만 생성되고 공유되도록 설계하는 것입니다.
=> 하나씩 일어나는 것
싱글톤 애플리케이션
public class SingletonService {
private static final SingletonService instance = new SingletonService();
public static SingletonService getInstance(){
return instance;
}
private SingletonService(){
}
public void logic(){
System.out.println("싱글톤 객체");
}
}
- 신규를 비공개로 올려 차단했습니다.
- 각 호출은 동일한 개체 인스턴스를 반환합니다.
@Test
@DisplayName("싱글톤 패턴을 사용")
void singletonServiceTest(){
SingletonService instance1 = SingletonService.getInstance();
SingletonService instance2 = SingletonService.getInstance();
System.out.println("instance1 = " + instance1);
System.out.println("instance2 = " + instance2);
Assertions.assertThat(instance1).isSameAs(instance2);
//same ==
//equal equals메서드
}
결과
인스턴스1 = hello.core.singleton.SingletonService@6ee12bac
Instance2 = hello.core.singleton.SingletonService@6ee12bac
※ 싱글톤 패턴을 구현하는 방법은 여러가지가 있습니다.
이 예는 가장 쉽고 편리한 방법입니다.
싱글톤 패턴의 문제점
- 싱글톤 패턴을 구현하는 코드가 많이 있습니다.
- 클라이언트는 종속성에서 구체적인 클래스에 의존 => DIP 위반
- 클라이언트가 구체적인 클래스에 의존하여 OCP 원칙을 위반할 가능성이 매우 높습니다.
- 테스트하기 어렵다
- 내부 속성을 변경하거나 초기화하기 어렵습니다.
- 개인 생성자로 하위 클래스를 만드는 것은 어렵습니다.
- 유연성이 나쁩니다.