public class SingletonService{
//1. static 영역에 객체를 1개만 생성
private static final SingletonService instance = new SingletonService();
//2. public으로 열어서 객체 인스턴스가 필요하면 이 static 메서드를 통해서만 조회하도록 허용
public static SingletonService getInstance(){
return instance;
}
//3. 생성자를 private로 선언해서 외부에서 new 키워드를 사용한 객체 생성을 못하게 막는다.
private SingletonService(){}
public void logic(){
System.out.println("싱글톤 객체 로직 호출");
}
}
싱글톤 패턴을 적용하면 고객의 요청이 올 때 마다 객체를 생성하는 것이 아니라, 이미 만들어진 객체를 공유해서 효율적으로 사용할 수 있다.
스프링 컨테이너는 싱글톤 패턴의 문제점을 해결하면서, 객체 인스턴스를 싱글톤으로 관리한다.
- 무상태로 만들라는 건 필드를 아예 쓰지 말라는 뜻이 아니라, 요청마다 달라지는 값을 필드에 저장하지 말라는 뜻
- Repository, Service, Client 같은 의존 객체를 final 필드로 주입받는 것은 괜찮
- userId, price, currentOrder처럼 사용자별로 달라지는 값은 필드가 아니라 파라미터, 지역 변수, 반환값으로 처리해야 함
스프링 컨테이너는 싱글톤 레지스트리다. 따라서 스프링 빈이 싱글톤이 되도록 보장해주어야 한다. 그런데 스프링이 자바 코드까지 어떻게 하기는 어렵다. 자바 코드는 여러번 호출될 수 있다. 그래서 스프링은 클래스의 바이트코드를 조작하는 라이브러리를 사용한다.
모든 비밀은 @Configutation을 적용한 AppConfig에 있다.
AnnotationConfigApplicationContext에 파라미터로 넘긴 값은 스프링 빈으로 등록된다. 그래서 AppConfig도 스프링 빈이 된다.프록시 적용 대상
- "스프링이 메서드 호출을 가로채야 하는 이유가 있는지"로 정한다.
- 비즈니스 빈 -> 객체 하나 만들고 주입하면 싱글톤 보장 끝, 기본 프록시 불필요
@Configuration,@Transactional,@Cacheable,@Async<- 프록시 대상