일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Today
- Total
- qualifier
- 빈 중복 오류
- autowired
- docker
- 스프링 컨테이너
- Spring interceptor
- DI컨테이너
- 라즈베리파이
- 도커
- 롬복 Qualifier
- 스프링
- DI
- 스프링 Configuration
- Servlet Filter
- RequiredArgsConstructor
- 의존관계 주입
- 생성자 주입
- ComponentScan
- springsecurity
- 싱글톤 컨테이너
- beandefinition
- 라즈베리파이4
- Spring
- 스프링 싱글톤
- 스프링 빈
- UsernamePasswordAuthenticationFilter
- 객체지향
- HandlerMethodArgumentResolver
- Autowired 옵션
- 스프링 빈 조회
그날그날 공부기록
싱글톤 컨테이너 본문
public class SingletonTest {
@Test
@DisplayName("스프링 없는 순수한 DI 컨테이너")
void pureContainer(){
AppConfig appConfig = new AppConfig();
//1. 조회: 호출할 때 마다 객체를 생성
MemberService memberService = appConfig.memberService();
//2. 조회: 호출할 때 마다 객체를 생성
MemberService memberService2 = appConfig.memberService();
//참조값이 다른 것을 확인
System.out.println("memberService = " + memberService);
System.out.println("memberService2 = " + memberService2);
Assertions.assertThat(memberService).isNotSameAs(memberService2);
}
}
위의 코드처럼 요청마다 새로운 인스턴스를 생성하고, 삭제하게 된다면 메모리의 낭비가 매우 심해진다.
이에 대한 해결방안은 인스턴스를 하나만 생성하는 것이다.
인스턴스를 하나만 생성하고, 공유시킨다면 메모리의 낭비를 없앨 수 있다.
이렇게 인스턴스가 1개만 생성되는 것을 보장하는 것이 바로 싱글톤 디자인 패턴이다.
싱글톤 패턴
싱글톤 패턴을 구현하는 예 중 하나를 적용해보았다.
public class SingletonService {
//static으로 객체를 하나만 생성.
private static final SingletonService instance = new SingletonService();
//해당 static 메서드로만 인스턴스 조회를 허용
public static SingletonService getInstance() {
return instance;
}
//private 생성자로 외부에서 new 키워드를 이용한 객체 생성 차단.
private SingletonService(){}
public void logic(){
System.out.println("싱글톤 객체 로직 호출");
}
}
SingletonService 인스턴스를 static으로 하나만 생성한다.
생성된 인스턴스를 조회하기 위해 public으로 조회 메서드를 생성한다.
생성자를 private으로 선언해서 SingletonService 객체를 외부에서 생성할 수 없도록 한다.
→ getInstance()로 조회하면 항상 같은 인스턴스를 사용한다.
실제 같은 인스턴스가 조회되는지 확인하기 위해 코드를 작성하여 확인해보면
@Test
@DisplayName("싱글톤 패턴을 적용한 객체 사용")
void singletonServiceTest(){
SingletonService service1 = SingletonService.getInstance();
SingletonService service2 = SingletonService.getInstance();
System.out.println("service1 = " + service1);
System.out.println("service2 = " + service2);
Assertions.assertThat(service1).isSameAs(service2);
//Assertions.assertThat(service1).isEqualTo(service2);
}
다음과 같이 동일한 객체임을 확인할 수 있다.
싱글톤 패턴을 사용하면 앞서 말한 장점도 있지만 단점 또한 존재한다.
- 싱글톤 패턴을 구현하는 코드가 항상 필요하다
- 의존관계상 클라이언트가 구체 클래스에 의존해 DIP를 위반하게 된다.
- DIP를 위반하기 때문에 OCP 역시 위반할 가능성이 높다.
- 유연한 테스트를 하기 어렵다.
- 내부 속성을 변경하거나 초기화 하기 어렵다.
- private 생성자로 자식 클래스를 만들기 어렵다.
- 유연성이 떨어진다.
이러한 단점 때문에 안티패턴이라고 불리기도 한다.
싱글톤 컨테이너
스프링 컨테이너는 직접 싱글톤 패턴을 적용하지 않아도 객체들을 싱글톤으로 관리하고, 위에서 말한 싱글톤 패턴의 단점을 해결해준다.
→ 사용자는 해당 패턴이나 단점에 얽매이지 않고 자유롭게 사용할 수 있다.
스프링 컨테이너는 싱글톤 컨테이너의 역할을 한다. 이렇게 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라고 한다.
맨 처음 작성한 코드를 스프링 컨테이너를 사용하여 다시 작성해 보았다.
@Test
@DisplayName("스프링 컨테이너와 싱글톤")
void springContainer(){
//AppConfig appConfig = new AppConfig();
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
//1. 조회: 호출할 때 마다 객체를 생성
MemberService memberService = ac.getBean("memberService", MemberService.class);
//2. 조회: 호출할 때 마다 객체를 생성
MemberService memberService2 = ac.getBean("memberService", MemberService.class);
//참조값이 같은 것을 확인
System.out.println("memberService = " + memberService);
System.out.println("memberService2 = " + memberService2);
Assertions.assertThat(memberService).isSameAs(memberService2);
}
AppConfig 설정파일에는 싱글톤 패턴과 관련된 코드가 하나도 없지만 스프링 컨테이너는 객체들을 알아서 싱글톤으로 관리해준다.
싱글톤으로 관리되는 같은 Bean을 호출하였으므로 당연히 같은 인스턴스인 것을 확인할 수 있다.
스프링 컨테이너는 기본적으로 빈을 싱글톤으로 관리하지만 요청할 때 마다 새로운 객체를 생성하여 반환하게 할 수도 있다고 한다.
'Spring 공부' 카테고리의 다른 글
스프링의 @Configuration과 싱글톤 (0) | 2022.07.21 |
---|---|
싱글톤 방식의 주의점 (0) | 2022.07.21 |
BeanDefinition (0) | 2022.07.18 |
BeanFactory & ApplicationContext (0) | 2022.07.15 |
스프링 빈 조회 (0) | 2022.07.11 |