[Spring]싱글톤 패턴의 개념 및 예제
싱글톤 패턴이란?
- 싱글톤 패턴이란 객체의 인스턴스가 1개만 생성되는 것을 보장하는 디자인 패턴입니다. -> 객체 인스턴스를 2개 이상 생성하지 못하도록 막아야 하고 private를 사용해서 외부에서 new 키워드를 사용해서 객체를 인스턴스 생성하는 것을 못하도록 막아야 합니다.
싱글톤 패턴 만드는 방법
public class Singleton {
private static final Sigleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
위에 있는 코드처럼 하면 객체의 인스턴스는 1개만 생성할 수 있습니다.
그런데 이렇게 작성할 경우 문제점이 있습니다.
문제점은 아래에서 확인해 보겠습니다.
싱글톤 패턴의 문제점
- 싱글톤 패턴을 구현하는 코드 자체가 많이 들어갑니다.
- 의존 관계 클라이언트가 추상화 클래스에 의존하는 게 아니라 구체 클래스에 의존하게 되면서 객체지향 설계 5원칙인 SOLID 중 DLP를 위반하고 OCP원칙을 위반할 가능성이 높습니다.
- 내부 속성을 변경하고 초기화하는 게 어렵고 private 생성자로 자식 클래스를 만들기가 어렵습니다.
이러한 문제점을 해결하기 위해서는 스프링 컨테이너를 사용합니다.
스프링 컨테이너
- 스프링 컨테이너는 싱글톤 패턴의 문제를 해결하면서 객체의 인스턴스를 싱글톤으로 관리합니다.
- 스프링 빈이 싱글톤으로 관리되는 빈입니다다.
- 싱글톤 패턴을 적용하지 않아도 객체 인스턴스를 싱글톤으로 관리합니다다.
- 스프링 컨테이너는 싱글톤 컨테이너 역할을 하고 이렇게 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라 합니다.
-> 스프링 컨테이너의 이런 기능 덕분에 싱글톤 패턴의 모든 단점을 해결하면서 객체를 싱글톤으로 유지할 수 있습니다.
- 스프링의 기본 빈 등록은 싱글톤입니다다.
싱글톤 방식의 주의점
- 싱글톤 패턴은 객체의 상태를 유지하게 설계를 하면 안 됩니다.
- 무상태로 설계를 해야 됩니다.
상태 유지 설계 코드
public class Stateful {
private String name;
String studentAddress(String name, String address) {
System.out.println(name + "학생의 주소는 " + address);
this.name = name;
return name;
}
public String getName() {
return name;
}
public static void main(String[] args) {
//스프링 컨테이너에 설정 정보에 등록된 빈을 등록
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Test.class);
// ac.getBean을 하여 스프링 컨테이너에 등록된 빈을 반환
Stateful stateful1 = ac.getBean(Stateful.class);
Stateful stateful2 = ac.getBean(Stateful.class);
stateful1.studentAddress("hoestory","대한민국");
stateful2.studentAddress("hoe", "미국");
System.out.println("stateful1.getName = " + stateful1.getName());
// stateful1.getName = hoe
}
static class Test {
@Bean
public Stateful stateful() {
return new Stateful();
}
}
}
결과값은 "hoestory"가 나와야 되는데 "hoe"가 나올 것입니다.
이유는 상태가 유지된 상태 stateful2.studentAddress("hoe", "미국"); 을 하여 name 부분에 "hoestory"에서 "hoe"로 변경되었기 때문입니다. 이렇게 되는 이유는 스프링 컨테이너에 빈으로 등록된 stateful 빈이 객체의 인스턴스를 한 번만 생성하기 때문에 stateful1과 stateful2는 같은 인스턴스입니다.
무상태 설계
- 특정 클라이언트에 의존적인 필드가 있으면 안 됩니다.
- 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안 됩니다.
- 필드 대신 자바에서 공유되지 않는 지역변수 파라미터 등을 사용해야 됩니다.
public class Stateful {
String studentAddress(String name, String address) {
System.out.println(name + "학생의 주소는 " + address);
return name;
}
public static void main(String[] args) {
//스프링 컨테이너에 설정 정보에 등록된 빈을 등록
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Test.class);
// ac.getBean을 하여 스프링 컨테이너에 등록된 빈을 반환
Stateful stateful1 = ac.getBean(Stateful.class);
Stateful stateful2 = ac.getBean(Stateful.class);
String student1 = stateful1.studentAddress("hoestory","대한민국");
String student2 = stateful2.studentAddress("hoe", "미국");
System.out.println("statefu1.getName() = " + student1);
// stateful1.getName() = hoestory
}
static class Test {
@Bean
public Stateful stateful() {
return new Stateful();
}
}
}
결과값은 상태 유지 코드의 결과값과 달리 상태가 유지 안되어서 "hoestory"가 나올 것입니다.
'Spring Boot' 카테고리의 다른 글
[Spring] @ScriptAssert 오류내용 및 해결방법 (0) | 2021.12.28 |
---|---|
[Spring] 메시지, 국제화 개념 및 사용 방법 (0) | 2021.12.26 |
[Spring]@RestController, @Controller 개념 및 예시 (0) | 2021.12.19 |
[Spring]스프링 부트 중복으로 빈을 등록했을때 해결 방법(@Autowired, @Qualifier, @Primary) (1) | 2021.11.01 |
[Spring]스프링부트 H2 데이터베이스 연동 오류 (2) | 2021.11.01 |
댓글
이 글 공유하기
다른 글
-
[Spring] 메시지, 국제화 개념 및 사용 방법
[Spring] 메시지, 국제화 개념 및 사용 방법
2021.12.26 -
[Spring]@RestController, @Controller 개념 및 예시
[Spring]@RestController, @Controller 개념 및 예시
2021.12.19 -
[Spring]스프링 부트 중복으로 빈을 등록했을때 해결 방법(@Autowired, @Qualifier, @Primary)
[Spring]스프링 부트 중복으로 빈을 등록했을때 해결 방법(@Autowired, @Qualifier, @Primary)
2021.11.01 -
[Spring]스프링부트 H2 데이터베이스 연동 오류
[Spring]스프링부트 H2 데이터베이스 연동 오류
2021.11.01