[Spring] Singleton Container
Singleton Pattern에 문제점
1. 싱글톤 패턴 구현을 위한 부가적인 코드가 많이 들어간다. 예를 들면 static final intance, private 생성자 등
2. 의존관계에 있어서 클라이언트가 구체 클래스 자체에 의존하게 된다. DIP(의존 관계 역전의 원칙)를 위반하게 된다. 클라이언트가 구체 클래스에 의존하기 때문에 OCP(개방-폐쇄 원칙) 또한 위반할 가능성이 높다.
3. 테스트 작성이 어렵다.
4. 내부 속성을 변경하거나 초기화하기 어렵다.
5. private 생성자이기 때문에 자식 클래스를 만들기 어렵다. 유연성 또한 떨어진다.
Spring에서 사용하는 Spring container는 singleton pattern에 문제점을 해결하고 객체 인스턴스를 singleton으로 관리하도록 도와준다.
Sigleton Container
1. Spring container는 singleton pattern을 적용하지 않아도 객체 인스턴스를 singleton으로 관리한다. 인스턴스를 출력해보면 같은 인스턴스를 가리키는 것을 알 수 있다.
2. Spring container는 singleton container 역할을 한다. singleton 객체를 생성하고 관리하는 기능을 singleton 레지스트라고 한다.
3. Spring container는 singleton pattern의 문제점을 해결하고 객체를 singleton으로 유지하도록 한다.
4. singleton 구현을 위한 부가적인 코드들이 필요하지 않다. 예를 들면 private 생성자 등
5. Spring의 기본 빈 등록을 위한 방식은 singleton이지만 scope를 설정해주면 요청시 마다 새로운 객체를 생성하여 반환할 수 있다.
6. Spring container는 빈에 등록된 객체는 여러번 호출하여도 container에 있는 빈을 자동으로 찾아서 주입해준다. 그 역할은 @Configuration가 적용된 Config 클래스가 하게 된다.
Singleton 방식을 사용할 때 주의할 점
1. 여러 클라이언트가 하나의 객체 인스턴스를 공유하기 때문에 singleton 객체는 상태를 유지하도록 설계하면 안된다. (stateful)
2. stateless하게 설계해야 한다.
2-1. 특정 클라이언트에 의존적인 필드가 있으면 안된다.
2-2. 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.
2-3. 읽기만 가능해야 하고, 일반적인 필드 대신 Java에서 공유되지 않는 지역변수, ThreadLocal등을 사용해야 한다.
3. 특히 Spring 빈의 필드에 공유되는 값을 설정하면 큰 장애가 발생할 수 있다. 예를 들면 나의 id 이지만 남의 결제 내역이 조회될 수 있다.
References.