[Spring] 싱글톤 컨테이너(Singleton Container)
Updated:
1. 개요
스프링 컨테이너는 싱글톤 컨테이너 역할을 하여 싱글턴 패턴의 단점들을 해결하면서 객체를 싱글톤으로 유지할 수 있다. 이번에는 싱글톤 컨테이너(Singleton Container)에 대해 알아보도록 하자.
2. 일반 DI 컨테이너
스프링을 사용하지 않는 경우 일반적으로 요청할 때마다 새로운 객체 인스턴스를 생성하여 반환한다. 따라서 메모리 낭비가 심하다는 단점이 있다.
[AppConfig.java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
public DiscountPolicy discountPolicy() {
return new RateDiscountPolicy();
}
}
[SingletonTest.java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class SingletonTest {
@Test
void pureContainer() {
AppConfig appConfig = new AppConfig();
MemberService memberService1 = appConfig.memberService();
MemberService memberService2 = appConfig.memberService();
System.out.println("memberService1 = " + memberService1);
System.out.println("memberService2 = " + memberService2);
assertThat(memberService1).isNotSameAs(memberService2);
}
[실행결과]
3. 싱글톤 패턴
싱글톤 패턴이란 객체 인스턴스를 한 개만 생성하여 전역적으로 접근 가능하도록 하는 패턴이다.
3-1. 싱글톤 패턴 예제
[SingletonService.java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class SingletonService {
private static final SingletonService instance = new SingletonService();
public static SingletonService getInstance() {
return instance;
}
private SingletonService() {}
public void logic() {
System.out.println("싱글톤 객체 로직 호출");
}
}
Line 3 : static 영역에 인스턴스 생성
Line 5 ~ 7 : 인스턴스 조회 시 항상 같은 인스턴스 반환
Line 9 : 생성자는 private으로 정의하여 외부에서 new로 생성이 불가능하도록 막음
[singletonServiceTest.java]
1
2
3
4
5
6
7
8
9
10
@Test
void singletonServiceTest() {
SingletonService singletonService1 = SingletonService.getInstance();
SingletonService singletonService2 = SingletonService.getInstance();
System.out.println("singletonService1 = " + singletonService1);
System.out.println("singletonService2 = " + singletonService2);
assertThat(singletonService1).isSameAs(singletonService2);
}
[실행 결과]
3-2. 싱글톤 패턴의 문제점
-
싱글톤 패턴을 구현하기 위한 코드 필요
-
구체 클래스에 의존하므로 DIP, OCP 위반
-
private 생성자로 인해 자식클래스 생성이 불가능하여 유연성 떨어짐
4. 싱글톤 컨테이너
싱글톤 컨테이너를 통해 싱글톤 패턴의 문제점들을 해결할 수 있다.
싱글톤은 동일한 객체 인스턴스를 공유하므로 상태를 가지고 있는 경우 다른 객체에 의해 의도치 않게 상태가 변경될 수 있다. 따라서 스프링 빈은 무상태(Stateless)로 설계되어야 한다.
[AppConfig.java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@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();
}
@Bean
public DiscountPolicy discountPolicy() {
return new RateDiscountPolicy();
}
}
[SingletonTest.java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class SingletonTest {
@Test
void springContainer() {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
MemberService memberService1 = ac.getBean("memberService", MemberService.class);
MemberService memberService2 = ac.getBean("memberService", MemberService.class);
System.out.println("memberService1 = " + memberService1);
System.out.println("memberService2 = " + memberService2);
assertThat(memberService1).isSameAs(memberService2);
}
}
[실행결과]
Leave a comment