JAVA Singleton pattern
- 오직 한 개의 인스턴스 생성을 보증하여 효율을 찾을 수 있지만 문제점이 많다.
- 클래스는 클래스로더마다 한 번만 인스턴스화 해야 한다.
- 외부 클래스로부터 인스턴화 되는 것을 막기위해 생성자는 private으로 선언해야 한다.
- 인스턴스화된 클래스를 static변수로 선언 / 인스턴스화 된 클래스를 리턴하는 함수를 선언
Spring Singleton pattern
- 컨테이너 내에서 특정 클래스에 대해 @Bean이 정의되면 스프링 컨테이너는 그 클래스에 대해 딱 한 개의 인스턴스를 만든다. 이 공유 인스턴스는 설정정보에서 관리되고, Bean이 호출될 때마다 스프링은 생성된 공유 인스턴스를 리턴 시킨다.
- Bean의 관리주체인 스프링 컨테이너는 항상 단일 공유 인스턴스를 리턴시키므로 Thread Safety도 자동보장된다.
Singleton pattern 주의점
- 객체 인스턴스를 하나만 생성해서 공유하는 상황에서 객체 인스턴스를 공유하기 때문에
객체 상태를 유지(stateful)하게 설계하면 안된다.
Java Singleton , Spring singleton 차이점
- java의 싱글톤은 클래스 로더에 의해 구현되고, 스프링 싱글톤은 스프링 컨테이너에 의해 구현된다.
- java의 싱글톤의 scope는 코드 전체이고, 스프링 싱글톤의 scope는 해당 컨테이너 내부이다.
- 스프링에 의해 구현된 싱글톤 패턴은 Thread safety를 자동으로 보장한다.
하지만, java의 싱글톤의 경우 구현하는 개발자의 로직에 따라 보장될 수도 있고 아닐 수도 있다.
JAVA Singleton pattern
- 객체의 인스턴스가 오직 1개만 생성되는 패턴
- 소프트웨어 디자인 패턴에서 Singleton pattern을 따를 클래스는
생성자가 여러 차례 호출되더라도 실제로 생성되는 객체를 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성한 객체를 리턴한다. (ex. DBCP(DataBase Connection Pool))
- 예제
package kail.study.java.design.single;
public class Printer {
private static Printer printer = null;
private Printer(){}
public static Printer getInstance() {
if(printer == null) {
printer = new Printer();
}
return printer;
}
public void print(String input) {
System.out.println(input);
}
}
/*
기본생성자를 private를 사용하여 생성을 불가능하게 하고
getInstance를 통해서만 생성이 가능하다.
getInstance는 내부적으로 생성되지 않았으면 생성하고,
기존에 생성된 값이 존재하면 생성된 instance를 리턴하기에
프로그램 전반에 걸쳐 하나의 인스턴스를 유지한다.
*/
//인스턴스를 제공하는 메서드와 인스턴스 변수 모두 Static으로 선언된 정적 변수 및 메서드다.
//기본생성자를 통해 생성할 수 없기 때문에 외부에서 인스턴스에 접근하려면
//클래스 변수 및 메서드에 접근을 허용해야 한다.
//public > protected > default > private
//public : 접근을 제한이 없음
//protected : 동일한 패키지 내에 존재하거나 파생클래스에서만 접근 가능
//default : 아무런 접근 제한자를 명시하지 않으면 default 값이 되며, 동일한 패키지 내에서만 접근이 가능
//private : 자기 자신의 클래스 내에서만 접근이 가능
- 사용 이유
1) 메모리
최초 한번의 new연산자를 통해 고정된 메모리 영역을 사용하기 때문에 추후 해당 객체에 접근할 때 메모리 낭비방지
+ 이미 생성된 인스턴스를 활용하기 때문에 속도도 빠름
2) 다른 클래스 간 데이터공유가 쉽다.
싱글톤 인스턴스가 전역으로 사용되기 때문에 다른 클래스의 인스턴스들이 접근하여 사용 가능 (데이터 동시성 문제 있을 수 있음.)
3) 도메인관점에서 인스턴스가 한 개만 존재하는 것을 보증하고 싶을 때
- 문제점
1) Multi-Thered환경에서 안전하지 않다.
- 여러 쓰레드가 공유될 때 여러개의 인스턴스 발생할 수 있음
- 인스턴스가 상태를 유지해야 할 때 각기 다른 쓰레드에서 공유하고 서로 다른 프로세스에서 처리하기 때문에 값이 일관되지 않을 수 있다.
2) 각 객체간의 결합도가 높아 변경에 유연하게 대처할 수 없다.
- 싱글톤은 프로그램 전체에서 하나의 객체만을 공통으로 사용하고 있기 때문에 각 객체간의 결합도가 높아지고 변경에 유연하게 대처할 수 없다. 싱글톤 객체가 변경되면 이를 참조하고 있는 모든 값들이 변경되어야 한다.
- 문제점 해결방법(2)
1) 정적변수에 인스턴스를 만들어 바로 초기화하는 방법
- 정적 변수는 객체가 생성되기 전 클래스가 메모리에 로딩할 때 만들어져 초기화가 한번만 실행된다.
- 또, 정적 변수는 프로그램이 시작될 때부터 종료될 때까지 없어지지 않고 메모리에 계속 상주하며 클래스에서 생성된 모든 객체에서 참조할 수 있다.
- synchronized를 통해 여러 쓰레드를 동시에 접근하는 것을 막는 방법도 있다.
2) 인스턴스를 만드는 메서드에 동기화하는 방법
- 인터페이스를 구현하는 경우 정적 클래스를 사용할 수 없다.(인터페이스가 정적 메서드를 가질 수 없다.)
Spring Singleton pattern
- Spring Container == Singleton Container라고 봐도 된다.
스프링 컨테이너는 싱글톤 패턴을 따로 적용안해도 객체 인스턴스가 싱글톤으로 관리된다.
+ 싱글톤 패턴을 위한 코드가 생략됨.
+ DIP, OCP, 테스트코드, private생성자 -> 자유롭게 싱글톤 사용 가능
- 스프링의 빈 등록방식은 기본적으로 싱글톤이다. 하지만 싱글톤이 아닌 요청할 때 마다 새로운 객체를 생성해서 반환하는 기능도 제공한다.
[참고]
1. 자바 싱글톤
https://tecoble.techcourse.co.kr/post/2020-11-07-singleton/
2. 스프링 싱글톤
https://jhhan009.tistory.com/77
https://velog.io/@jaeeunxo1/spring-singleton
3. 자바싱글톤과 스프링 싱글톤의 차이
https://judekim.tistory.com/91
'차근차근 > Spring' 카테고리의 다른 글
Annotation (0) | 2021.12.09 |
---|---|
2.용어정리(6)-SPA (0) | 2021.12.09 |
2.용어정리(4)-ViewResolver,prefix,suffix (0) | 2021.12.09 |
2.용어정리(3)-AOP (0) | 2021.12.08 |
2.용어정리(1)-Model1,Model2,SpringMVC,POJO (0) | 2021.12.08 |