애플리케이션이 시작될 때, 어떤 클래스가 최초 한번만 메모리를 할당하고 그 메모리에 인스턴스를 만들어 사용하는 디자인패턴이다. 따라서 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 단 하나이며, 최초 생성 이후에 호출된 생성자는 최초에 생성한 객체를 반환한다.
public class SingletonInstance {
// 1
private static final SingletonInstance instance = new SingletonInstance();
// 2
public static SingletonInstance getInstance() {
return instance;
}
// 3
private SingletonInstance() {
}
}
주석 1 : static 변수를 사용하여 인스턴스가 사용되는 시점이 아닌 클래스가 로딩되는 시점에 실행하도록 한다.
주석 2 : getInstance 메서드를 통해서만 해당 객체를 얻을 수 있도록 한다.
주석 3 : 생성자를 private으로 지정하여 new를 통한 객체 생성이 불가능하도록 한다.
public class SingletonInstance {
private SingletonInstance() {
}
private static SingletonInstance instance = null;
public synchronized static SingletonInstance getInstance() {
if (instance == null) {
instance = new SingletonInstance();
}
return instance;
}
}
요청이 있을 때마다 객체를 생성하는 것이 아니라, 이미 생성되어진 객체를 공유하여 재사용이 가능하여 메모리 방지를 방지할 수 있다.
싱글톤 패턴의 문제점을 해결하면서, 따로 싱글턴 패턴을 적용하지 않아도 기본적으로 객체를 싱글톤으로 유지할 수 있는 컨테이너
객체 인스턴스를 하나만 생성하여 여러 클라이언트가 하나의 객체 인스턴스를 공유하기 때문에 상태를 유지하게 설계하면 안된다. → 무상태(stateless) 설계
특정 클라이언트에 의존적인 필드가 있으며 안되며, 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다.
→ 필드 대신 자바에서 공유되지 않는, 로컬변수, 파라미터 등을 사용해야한다.
private int age;
public void introduce(String name, int age) {
System.out.println("이름은 " + name + "이고, 나이는 " + age + "살 이다.");
this.age = age;
}
public int getAge() {
return age;
}
public int introduce(String name, int age) {
System.out.println("이름은 " + name + "이고, 나이는 " + age + "살 이다.");
return age;
}
스프링 컨테이너가 기본적으로 객체를 싱글톤으로 유지하게 하게끔 하는 핵심은 @Configuration 이다.
@Test
void checkBeanClass() {
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
AppConfig bean = ac.getBean(AppConfig.class);
System.out.println("bean = " + bean.getClass());
}
위 테스트 코드를 통해 1) @Configuration이 붙은 설정 클래스(AppConfig.class)의 클래스명 과
2) @Configuration이 붙지 않는 순수 설정 클래스(AppConfig.class)의 클래스명 을 출력하여 비교해보았을 때,
1) bean = class hello.core.AppConfig$$EnhancerBySpringCGLIB$$9db1a227
2) bean = class hello.core.AppConfig
@Configuration이 붙은 설정 클래스명 뒤에 추가적으로 $$EnhancerBySpringCGLIB$$9db1a227
있는 것을 확인 할 수 있다.
설정 클래스에 @Configuration가 붙으므로써, 그 설정 파일은 순수 클래스가 아닌 CGLIB라는 바이트코드 조작 라이브러리를 사용하여 기존의 AppConfig 클래스를 상속받은 임의의 다른 클래스를 생성하여 스프링 빈으로 등록한다.
→ 기존 AppConfig 클래스가 아닌 AppConfig@CGLIB 클래스가 스프링 빈으로 등록된다.
AppConfig@CGLIB는 설정 클래스(AppConfig.class) 내에 @Bean이 붙은 객체를 스프링 빈으로 등록할 때, 이미 스프링 빈으로 등록된 객체에 대해서 존재하는 빈을 반환하고, 스프링 빈으로 등록되어 있지 않다면 생성하여 스프링 빈에 등록하고 반환한다.
→ 이를 통해 스프링 컨테이너는 자바 코드를 읽어 객체를 싱글톤으로 유지하고 관리한다.
https://www.inflearn.com/course/스프링-핵심-원리-기본편#
https://jeong-pro.tistory.com/86
https://maenco.tistory.com/entry/Spring-Container스프링-컨테이너-Singleton싱글톤