private 생성자를 사용해 외부에서 임의로 new 키워드를 사용하지 못하도록 막아야 함
예시)
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() { }
}
싱글톤 패턴을 적용하면 고객의 요청이 올 때마다 객체를 생성하는 것이 아니라, 이미 만들어진 객체를 공유해서 효율적으로 사용할 수 있음
@Configuration
public class AppConfig {
@Bean
public MemberService memberService() {
return new MemberServieImpl(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
...
}
CGLIB를 사용해 AppConfig Bean 생성 시 위와 같이 (AppConfig 클래스를 상속한) 하위 클래스 객체를 생성함
AppConfig@CGLIB 예상 코드
@Bean
public MemberRepository memberRepository() {
if (memoryMemberRepository가 이미 스프링 컨테이너에 등록되어 있으면) {
return 스프링 컨테이너에서 찾아서 반환;
} else { // 스프링 컨테이너에 없으면
기존 로직 호출해 MemoryMemberRepository 객체 생성하고 스프링 컨테이너에 등록
return 반환
}
}
바이트코드 조작을 통해 타킷 클래스를 상속받은 하위 클래스를 생성했으므로, 메서드 오버라이딩 가능함
@Bean이 붙은 메서드마다 이미 스프링 빈이 존재하면 존재하는 빈을 반환하고, 스프링 빈이 없으면 생성해서 스프링 빈으로 등록한 뒤 반환하는 코드가 동적으로 만들어짐
덕분에 싱글톤이 보장되는 것
추가) @Configuration을 적용하지 않고, @Bean만 적용하면 어떻게 될까?
@Bean만 사용해도 스프링 빈으로는 등록되지만, @Configuration이 없어 CGLIB를 사용하지 않기 때문에 싱글톤 빈 을 보장하지 않음