싱글톤 패턴
싱글톤 패턴은 특정 클래스의 인스턴스가 하나만 생성 되도록 보장하고, 그 인스턴스에 쉽게 접근할 수 있는 글로벌 포인트를 제공하는 패턴입니다. 싱글톤 패턴 설정은 로거, 캐시, 스레드 풀, 데이터베이스 연결 등과 같이 한번만 생성되어 여러 곳에서 공유되어야 하는 객체에서 주로 사용됩니다.
1. 즉시 초기화
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return instance;
}
}
2. Lazy Initialization with Double Checked Locking
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
3. Static Inner Class (정적 내부 클래스)
public class Singleton {
private Singleton() {}
private static class Holder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return Holder.INSTANCE;
}
}
스프링에서의 싱글톤
스프링에서의 싱글톤은 자바에서의 전통적인 싱글톤 디자인 패턴과는 조금 다르게 동작합니다. 스프링에서 싱글톤이라는 말은 스프링의 빈 생명 주기와 관련이 있습니다.
1. 스프링 컨테이너 범위에서의 싱글톤
스프링에서 싱글톤이라는 것은 전체 JVM 범위 내에서의 유일한 인스턴스를 말하는 것은 아니며, 특정 스프링 컨테이너 ( ApplicationContext or BeanFactory) 범위 내에서 유일한 인스턴스를 보장한다는 의미 입니다. 따라서 스프링 컨테이너를 가진 어플리케이션에서는 동일한 빈 이름으로 여러 싱글톤 인스턴스가 존재할 수 있습니다.
package com.example;
import org.springframework.stereotype.Component;
@Component
public class SingletonBean {
public String getMessage() {
return "Instance: " + this;
}
}
-----
package com.example;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context1 = new AnnotationConfigApplicationContext();
context1.scan("com.example");
context1.refresh();
AnnotationConfigApplicationContext context2 = new AnnotationConfigApplicationContext();
context2.scan("com.example");
context2.refresh();
SingletonBean beanFromContext1 = context1.getBean(SingletonBean.class);
SingletonBean beanFromContext2 = context2.getBean(SingletonBean.class);
System.out.println(beanFromContext1.getMessage());
System.out.println(beanFromContext2.getMessage());
context1.close();
context2.close();
}
}
위 코드에서 beanFromContext1, beanFromContext2는 각각 다른 ApplicationContext에서 가져오므로 SingletonBean의 인스턴스 또한 다르게 생성됩니다. ( 참조 주소 다름 )
2. 빈의 생명주기
스프링에서 빈의 기본 스코프는 싱글톤 입니다. 즉, @Component, @Service, @Controller, @Repository 등의 어노테이션을 사용하여 빈으로 동록되는 클래스를 기본적으로 싱글톤 스코프를 가지게 됩니다. 스프링 컨테이너는 이러한 싱글톤 빈의 인스턴스를 처음 요청시 생성하고 그 이후의 요청에 대해서는 동일한 인스턴스를 반환합니다.
package com.example;
import org.springframework.stereotype.Service;
@Service
public class SingletonService {
public void printMessage() {
System.out.println("This is a singleton bean in Spring: " + this);
}
}
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class BeanUser {
@Autowired
private SingletonService singletonService;
public void useService() {
singletonService.printMessage();
}
}
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
public class SingletonExampleApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SingletonExampleApplication.class, args);
BeanUser beanUser1 = context.getBean(BeanUser.class);
beanUser1.useService();
BeanUser beanUser2 = context.getBean(BeanUser.class);
beanUser2.useService();
}
}
이 코드를 실행하면 SingletonService의 printMessage() 메서드가 두번 호출 되지만, 출력되는 참조주소는 동일하게 나타나게 됩니다. SingletonService 빈이 싱글톤 스코프를 가지며, 동일한 인스턴스가 재사용되고 있습니다.
'디자인패턴' 카테고리의 다른 글
디자인패턴 : 전략 패턴 (0) | 2024.05.09 |
---|---|
자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 - Supplier<T> 인터페이스가 팩토리를 표현하는 완벽한 예이다 (0) | 2024.04.17 |
행동 패턴 (0) | 2023.12.12 |
구조 패턴 (0) | 2023.12.12 |