728x90
Stack의 pop으로 문제상황 재현
- stack은 후입선출로서, 일반적으로
pop()메서드를 통해 후입선출 시 마지막 값을 return 하는 기능을 가지고 있다. - 참고로 아래 기능은 실제 Stack과 다르다. 해당 주제의 예시를 보여주기 위해 따로 만든 것이다.
public class chapter7 {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public chapter7() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public String getElements() {
return Arrays.toString(elements);
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e; //할당 이 후 size +1를 한다
}
public Object pop() {
if (size == 0)
throw new EmptyStackException();
return elements[--size]; // 먼저 size를 -1을 한 후 마지막 값 return
}
// stack size의 확장 메서드
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
- 위의 코드를 테스트해보면 하나의 문제점이 보인다.
public class run7 {
public static void main(String[] args) {
chapter7 stack = new chapter7();
// 스택에 요소 추가
stack.push("첫 번째 요소");
stack.push("두 번째 요소");
stack.push("세 번째 요소");
// 스택에서 요소 제거하고 출력
stack.pop();
stack.pop();
System.out.println("2번의 pop 이 후 \n " + stack.getElements());
// 스택에 새로운 요소 추가
stack.push("네 번째 요소");
stack.pop();
System.out.println("4번의 pop 이 후 \n " + stack.getElements());
}
}
- 출력 결과는 아래와 같다.
- 세 번째 요소는
pop()을 통해 사용하였기 때문에, 세 번째 요소는 꺼내졌음에도 불구하고 가비지 컬렉터가 회수하지 않았다. 즉, 다 쓴 참조를 여전히 가지고 있다는 뜻이다.
2번의 pop 이 후
[첫 번째 요소, 두 번째 요소, 세 번째 요소, null, null, null, null, null, null, null, null, null, null, null, null, null]
4번의 pop 이 후
[첫 번째 요소, 네 번째 요소, 세 번째 요소, null, null, null, null, null, null, null, null, null, null, null, null, null]
- 이를 해결하기 위해 다 쓴 요소는 null 처리를 해줄 것이다.
- 하지만 모든 경우를 null 처리하는 것이 무조건 좋은 것도 아니며, 코드의 가독성을 떨어뜨린다.
public Object pop() {
if (size == 0)
throw new EmptyStackException();
Object result = elements[--size];
elements[size] = null;
return result;
}
위 상황의 문제점은 스택이 자기 스스로 메모리를 관리하려고 하는 것이다. 비활성화 된 영역이었던 세 번째 객체도 가비지 컬렉터 관점에서 유효한 객체이기 때문이다.
[추가내용] 싱글톤 패턴과 Spring Bean
- 싱글톤은 생성자가
private로 직접 인스턴스를 생성할 수 없고, 외부에서 주입할 수도 없다. - Spring에서는 완전히 위와 같이 싱글톤을 사용하지 않는데, 그건 안티 패턴이기 때문이다.
- 일반적으로 Spring의 Bean들은 BeanFactory를 통해 관리되는데 Bean의 생명주기 Scope는 싱글톤을 따르고 있다.
- 실제로는
private static을 Spring에서는 사용하지 않는다고 한다. - 그 이유는 토비의 스프링을 참고하여 다음과 같다.
private으로 인해 상속 불가능- 테스트 어려움
- 실제 서버에서의 Instance 유일성 보장 못함
- 전역으로 쓸 수 있다는 것은 공유될 수 있다는 것이고 이건 객체지향에서는 권장되지 않음
- 그래서 Spring은 SingleTom Registry 방식을 사용한다고 한다.
싱글톤 레지스트리
- Spring 에서 제공하는 기능으로 Spring 컨테이너가 자체적으로 싱글톤 객체를 생성 및 관리하는 메커니즘을 말한다.
싱글톤 레지스트리 특징
- 자동관리: Sprng 컨테이너는 Bean의 정의에 따라 자동으로 싱글톤 인스턴스를 생성하고 관리한다.
- DI 지원: 싱글톤 객체에 대한 의존성 주입을 자동으로 처리한다.
- 유연한 스코프 관리: 기본적으로 싱글톤 스코프를 사용하지만 필요에 따라 프로토타입 스코프 등 다른 스코프로 설정할 수 있다.
예제 코드
@SpringBootApplication
public class SingletonRegistryExampleApplication {
public static void main(String[] args) {
SpringApplication.run(SingletonRegistryExampleApplication.class, args);
}
}
// 간단한 서비스 클래스 정의
@Service
public class SimpleService {
public String getServiceMessage() {
return "This is a singleton service instance.";
}
}
// 서비스를 사용하는 컨트롤러
@RestController
public class SimpleController {
private final SimpleService simpleService;
// 생성자를 통한 의존성 주입
@Autowired
public SimpleController(SimpleService simpleService) {
this.simpleService = simpleService;
}
@GetMapping("/message")
public String getMessage() {
return simpleService.getServiceMessage();
}
}728x90
'Programming Language > Java' 카테고리의 다른 글
| [이펙티브 자바]Item.09-try-finally보다는 try-with-resources를 사용하라 (0) | 2024.05.06 |
|---|---|
| [Java] 메모리 누수가 발생하는 케이스 (0) | 2024.05.03 |
| [이펙티브 자바]Item.06-불필요한 객체 생성을 피하라. (0) | 2024.04.06 |
| [이펙티브 자바]Item.05-자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) | 2024.04.05 |
| [이펙티브 자바]Item.04-인스턴스화를 막으려거든 private 생성자를 사용하라 (0) | 2024.04.05 |