스프링과 싱글톤 패턴의 관계 (Configuration)
- 싱글톤 패턴
- 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴
- private final로 인스턴스를 생성하여 외부에서 new 키워드를 사용하지 못하도록 막아야함
- 싱글톤 패턴을 지킨 코드
- getInstance 메서드를 통해서만 인스턴스를 생성할 수 있고
- private 생성자를 선언하여 외부에서 new 키워드로 접근하는 것을 막음
public class SingletonService {
//1. static 영역에 객체를 딱 1개만 생성해둔다.
private static final SingletonService instance = new SingletonService();
//2. public으로 열어서 객체 인스터스가 필요하면 이 static 메서드를 통해서만 조회하도록
허용한다.
public static SingletonService getInstance() {
return instance;
}
//3. 생성자를 private으로 선언해서 외부에서 new 키워드를 사용한 객체 생성을 못하게 막는다.
private SingletonService() {
}
- 싱글톤의 문제점
- 싱글턴 패턴을 구현하는 코드 자체가 많이 들어간다
- 의존관계상 클라이언트가 구체를 클래스에 의존한다 → DIP 위반
- 클라이언트가 구체 클래스에 의존해서 OCP 원칙을 위반할 가능성이 높다
- 테스트하기 어렵다
- 내부 속성을 변경하거나 초기화 하기 어렵다
- private 생성자로 자식 클래스를 만들기 어렵다]
- 결론적으로 유연성이 많이 떨어진다
- 안티패턴으로 불리기도 한다
- 이러한 싱글톤 패턴을 사용하는데 있어서 스프링 사용은 필수적이고 취약점을 보안해준다
- 싱글톤 컨테이너
- 스프링 컨테이너는 싱글톤 패턴의 문제점을 해결하면서, 객체 인스턴스를 싱글톤(1개만
- 생성) 으로 관리한다
- 스프링 컨테이너는 싱글톤 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리한다
- 스프링 컨테이너는 싱글톤 컨테이너 역할을 한다. 이렇게 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라 한다
- 스프링 컨테이너의 이런 기능 덕분에 싱글톤 패턴의 모든 단점을 해결하면서 객체를 싱글톤으로 유지할 수 있다
- 싱글톤 패턴을 위한 지저분한 코드가 들어가지 않아도 된다
- DIP, OCP,테스트,private 생성자로 부터 자유롭게 싱글톤을 사용할 수 있다
- 스프링 컨테이너를 사용하여 싱글톤이 지켜지는 지 확인
@TEST
@DisplayName("스프링 컨테이너와 싱글톤")
void springContainer() {
ApplicatinContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
//1. 조회: 호출할 때 마다 같은 객체를 반환
MemberService memberService1 = ac.getBean("memberService",MemberService.class);
//2. 조회: 호출할 때 마다 같은 객체를 반환
MemberService memberService2 = ac.getBean("memberService",MemberService.class);
//참조값이 같은 것을 확인
System.out.println("memberService1 = " + memberService1);
System.out.println("memberService2 = " + memberService2);
//memberService1 == memberService2
assertThat(memberService1).isSameAs(memberService2);
}
- AnnotationConfigApplicationContext은 Beandefinition에서 아래와 같은정보를 가져온다
- BeanClassName: 생성할 빈의 클래스 명(자바 설정 처럼 팩토리 역할의 빈을 사용하면 없음) factoryBeanName: 팩토리 역할의 빈을 사용할 경우 이름, 예) appConfig factoryMethodName: 빈을 생성할 팩토리 메서드 지정, 예) memberService Scope: 싱글톤(기본값) lazyInit: 스프링 컨테이너를 생성할 때 빈을 생성하는 것이 아니라, 실제 빈을 사용할 때 까지 최대한 생성을 지연처리 하는지 여부 InitMethodName: 빈을 생성하고, 의존관계를 적용한 뒤에 호출되는 초기화 메서드 명 DestroyMethodName: 빈의 생명주기가 끝나서 제거하기 직전에 호출되는 메서드 명 Constructor arguments, Properties: 의존관계 주입에서 사용한다. (자바 설정 처럼 팩토리 역할의 빈을 사용하면 없음)
- 결과
- 스프링 컨테이너 덕분에 고객의 요청이 올 때마다 객체를 생성하는 것이 아니라, 이미
- 만들어진 객체를 공유해서 효율적으로 재사용할 수 있다
- Configuration 과 싱글톤
- 스프링 컨테이너는 싱글톤 레지스트리다. 따라서 스프링 빈이 싱글톤이 되도록 보장해주어야 한다
- 스프링은 클래스의 바이트코드를 조작하는 라이브러리를 사용한다
- 바로 @Configuration을 적용한 AppConfig 에있다
'프로그래밍언어 > Java' 카테고리의 다른 글
[Java] ComponentScan 개념 (0) | 2022.01.20 |
---|---|
[Java] 의존관계 주입 방법 (0) | 2022.01.20 |
[Java]웹 어플리케이션과 싱글톤 (0) | 2022.01.18 |
[Java] DIP, OCP 원칙 (0) | 2022.01.17 |
스프링 자동 의존관계 , 수동 의존관계 (0) | 2022.01.13 |
댓글