객체가 java JVM안에 하나만 있어야하는 패턴
즉, 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴이다.
고객의 요청이 올 때마다 객체를 만들어서 반환해줘야함
이렇게 되면 jvm 메모리에 객체가 생성되어 계속 올라가게 됨
이럴때는 객체가 하나만 생성되고, 그것을 공유하도록 하면 된다.
package hello.core.singleton;
public class SingletonService {
private static final SingletonService instance = new SingletonService();
public static SingletonService getInstance() {
return instance;
}
private SingletonService() {
}
public void logic() {
System.out.println("싱글톤 객체 로직 호출");
}
}
스프링 컨테이너는 싱글톤 컨테이너 역할을 한다. 이렇게 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라고 한다.
스프링은 싱글톤 방식으로 동작한다.
싱글톤 방식은 여러 클라이언트가 하나의 객체를 공유하기 때문에 싱글톤 객체의 상태를 유지(stateful)하게 설계하면 안된다.
스프린 빈은 항상 무상태(stateless)로 설계해야한다.
- 특정 클라이언트에 의존적인 필드가 있으면 안됨
- 특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안됨
- 가급적 읽기만 가능해야함
- 필드 대신에 자바에서 공유되지 않는 지역변수, 파라미터, ThreadLocal을 사용해야 한다.
@Test
void ConfigurationDeep() {
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
AppConfig bean = ac.getBean(AppConfig.class);
System.out.println("bean = " + bean.getClass());
}
결과는 예상과는 다르게 xxxCGLIB가 붙어나온다.
이것은 스프링이 CGLIB라는 바이트코드 조작 라이브러리를 사용하여 AppConfig 클래스를 상속받은 임의의 다른 클래스를 만들고, 그것을 빈으로 등록한 것이다.
이 임의의 다른 클래스가 싱글톤을 보장하도록 해준다.
@Configuration을 붙이지 않고 @Bean만 사용하면 내가 원래 만들었던 AppConfig가 메모리에 등록된다.(CGLIB 사용x) 하지만 싱글톤은 보장되지 않는다.