일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 프로그래머스
- 스프링
- select
- 서브쿼리
- @Controller
- 코딩테스트
- 인프런
- STS
- MVC2
- @RestController
- 메이븐
- MVC
- 프레임워크
- 서블릿
- toUpperCase
- SQL
- Join
- Model1
- AOP
- 자바
- 기술 대비
- 김영한
- 세션
- 코테
- 뉴렉처
- DDL
- order by
- JSP
- 인텔리제이
- Model2
- Today
- Total
Heestory
05.스프링)싱글톤 컨테이너 본문
서론)
스프링이 없는 순수한 DI 컨테이너는 AppConfig에서 요청을 할 때마다 객체를 새로 생성
→ 고객 그래픽이 초당 100이 나오면 초당 100개 객체가 생성되고 소멸 → 메모리 낭비가 심하다
→ 해당 객체가 딱 1개만 설생되고, 공유하도록 설계한다 → 싱글톤 패턴
싱글톤 패턴
:글래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴
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(){
}
public void logic(){
System.out.println("싱글톤 객체 로직 호출");
}
}
문제점)
- 싱글톤 패턴을 구현하는 코드 자체가 많이 들어간다. getInstance()~ 늘 들어감
- 의존 관계상 클라이언트가 구체 클래스에 의존
- 클라이언트가 구체 클래스에 의존해서 OCP 원칙을 위반할 가능성이 높다
- 테스트하기 어렵다
- 내부 속성을 변경하거나 초기화 하기 어렵다
- private 생성자로 자식 클래스를 만들기 어렵다
- 유연성이 떨어진다
싱글톤 컨테이너
스프링 컨테이너는 싱글톤 패턴의 문제점을 해결하면서, 객체 인스턴스를 싱글톤(1개만 생성)으로 관리 → 싱글톤 컨테이너 역할, 싱글톤 레지스트리
싱글톤 방식의 문제점
싱글톤 상태를 무상태(stateless)로 설계해야 한다
public class StatefulService {
// private int price; //상태를 유지하는 필드
public int order(String name, int price){
System.out.println("name = "+name +" price =" +price);
// this.price = price; //여기가 문제!!
return price;
}
// public int getPrice(){
// return price;
// }
}
class StatefulServiceTest {
@Test
void statefulServiceSingleton(){
ApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);
StatefulService statefulService1 = ac.getBean(StatefulService.class);
StatefulService statefulService2 = ac.getBean(StatefulService.class);
//ThreadA : A 사용자 10000원 주문
int userAPrice = statefulService1.order("userA",10000);
//ThreadB : B 사용자 20000원 주문
int userBPrice = statefulService2.order("userB",20000);
//ThreadA : 사용자A 주문 금액 조회
// int price = statefulService1.getPrice();
System.out.println("price = "+ userAPrice);
// Assertions.assertThat(statefulService1.getPrice()).isEqualTo(20000);
}
static class TestConfig {
@Bean
public StatefulService statefulService() {
return new StatefulService();
}
}
}
@Configuration과 바이트 코드 조작의 마법
@Test
void configurationDeep(){
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
AppConfig bean = ac.getBean(AppConfig.class);
System.out.println("bean = "+bean.getClass());
}
- 스프링이 CGLIB 라는 바이트코드 조작 라이브러리를 사용해서 AppConfig 클래스를 상속받은 임의의 다른 클래스를 만들고, 그 다른 클래스를 스프링 빈으로 등록한 것 → 싱글톤 보장 되게 도와준다
: @Bean이 붙은 메서드마다 이미 스프링 빈이 존재하면 존재하는 빈을 반환하고, 스프링 빈이 없으면 생성해서 스프링 빈으로 등록하고 반환하는 코드가 동적으로 만들어진다.
만약 @Configuration 없이 @Bean만 적용한다면 @Configuration에 의해 CGLIB 기술이 사용되어 싱글톤이 적용되지만, @Bean만 사용한다면 스프링 빈으로 등록되지만, 승글톤은 보장되지 않는다
→ 스프링 설정 정보는 항상 @Configuration 을 사용하자
본 내용은 인프런 - 김영한 스프링 기본편 강의 내용 정리용으로 작성하였습니다
'개발(~국비) > Spring' 카테고리의 다른 글
07.스프링)의존관계 자동 주입 (0) | 2022.10.24 |
---|---|
06.스프링) 컴포넌트 스캔 (0) | 2022.10.24 |
04.스프링)스프링 컨테이너와 스프링 빈 (0) | 2022.10.22 |
02~03.스프링)핵심 원리 이해 (0) | 2022.10.22 |
01.스프링 (0) | 2022.10.20 |