728x90
반응형
개요
싱글톤 방식은 객체 인스턴스를 하나만 생성하여 그 인스턴스를 공유하기 때문에
클라이언트 들이 하나의 인스턴스에 접근을 합니다.
그런데 이때 인스턴스에 있는 필드 변수를 사용하게 되면 문제가 발생할 수 있습니다.
해결방법
싱글톤 방식은 무상태(stateless)로 설계 해야합니다.
1. 클라이언트에게 의존적인 필드가 있으면 안됩니다.
2. 클라이언트가 변경할 수 있는 필드가 있으면 안됩니다.
3. 가급적 필드에 대해 읽기만 가능해야 합니다.
4. 필드 대신 지역변수, 파라미터, ThreadLocal을 사용해야 합니다.
문제점에 대한 예시
- 필드를 사용하고 클라이언트가 직접 필드의 값을 변경하는 경우
//게임에서 점수를 측정하는 서비스
public class ScoreCheckService {
private int score; //필드를 선언!
public void game(String name, int score){
this.score = score; //필드의 값을 변경하는 경우!
}
public int getScore(){
return score; //필드에 score를 반환
}
}
public class ScoreCheckServiceTest {
public static void main(String[] args) {
//설정 파일에서 빈 정보를 가져옵니다.
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
//두 클라이언트가 빈을 호출해서 ScoreCheckService에 접근을 할 때
ScoreCheckService service1 = ac.getBean("ScoreCheckService", ScoreCheckService.class);
ScoreCheckService service2 = ac.getBean("ScoreCheckService", ScoreCheckService.class);
//첫번째 사용자가 98점을 받고 두번째 사용자가 70점을 받았다고 가정하면
service1.game("user1", 98);
service2.game("user2", 70);
//첫번째 사용자의 점수를 받아왔을 때
int user1_score = service1.getScore();
//출력 값은?
}
}
user1_score의 값은 70으로 출력됩니다. 왜냐하면 ScoreCheckService는 싱글톤이기 때문에
인스턴스가 하나로 공유되고 있는 상황입니다. 그런데 service2.game()에서 ScoreCheckService에 score에 접근을 하고
그 값을 변경했기 때문에 user1이 98점을 받았음에도 user2의 게임에서 70점이 공유하는 ScoreCheckService의
score 필드값에 70점이 들어가서 service1.getScore(); 점수를 가져왔을 때 70으로 출력되는 것입니다.
문제점에 대한 해결방법
- 지역변수를 사용하여 반환합니다.
//게임에서 점수를 측정하는 서비스
public class ScoreCheckService {
//private int score; //필드 지우기!
public void game(String name, int score){
//this.score = score; //필드의 값에 접근하지 않기!
return score; //점수를 바로 반환
}
//public int getScore(){
// return score; //필드에 score를 반환하는 메서드 지우기!
//}
}
public class ScoreCheckServiceTest {
public static void main(String[] args) {
//설정 파일에서 빈 정보를 가져옵니다.
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
//두 클라이언트가 빈을 호출해서 ScoreCheckService에 접근을 할 때
ScoreCheckService service1 = ac.getBean("ScoreCheckService", ScoreCheckService.class);
ScoreCheckService service2 = ac.getBean("ScoreCheckService", ScoreCheckService.class);
//사용자의 점수를 바로 지역변수로 받아서 사용합니다.
int user1_score = service1.game("user1", 98);
int user2_score = service2.game("user2", 70);
//첫번째 사용자의 점수를 출력했을 때 98점이 나오게 됩니다.
System.out.println(user1_score);
}
}
728x90
반응형
'Spring' 카테고리의 다른 글
[Spring] 관습적인 추상화 (2) | 2022.08.09 |
---|---|
[Spring] 객체 지향 설계의 다섯 가지 기본 원칙 - SOLID (0) | 2022.07.15 |
[Spring] @ComponentScan @Autowired 의존관계 자동 주입 (0) | 2022.07.12 |
[Spring] @Configuration과 Singleton By CGLIB (0) | 2022.07.11 |
[Spring] AppConfig을 통한 관심사 분리와 리팩터링 (0) | 2022.07.11 |