본문 바로가기

프로그래밍

[Spring] @Configuration과 싱글톤

웹 애플리케이션과 싱글톤

웹 애플리케이션은 보통 여러 고객이 동시에 요청한다.
이럴때마다 요청한 고객에게 모두 서로 다른 새로운 객체를 반환하면 메모리 낭비도 심하고 효율성이 떨어짐.
따라서 딱 1개의 객체만 생성하고 이걸 공유하도록 하면 됨. ->이게 바로 싱글톤!

하지만, [스프링없이 순수한 자바로만 싱글톤을 구현했을 때의 단점]
: 코드자체가 많이 들어감, DIP위반, OCP위반할 가능성 높아짐(구체클래스.getInstance()해야하므로), 유연성이 떨어짐, private생성자 때문에 자식클래스 만들기 어려움. …등등

싱글톤 컨테이너

스프링컨테이너는 객체 인스턴스를 싱글톤으로 관리. (객체 1개만 생성)
싱글톤패턴을 적용하지 않아도 자동으로 싱글톤으로 관리.

싱글톤 방식의 주의점

싱글톤 방식은 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에 주의.
특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안됨!
Ex) 잘못된 코드 예시 : ThreadA는 만원을 주문, ThreadB는 이만원을 주문. ThreadA의 주문금액을 출력->2만원이라고 나옴.
-> 공유필드 조심!! 스프링 빈은 항상 무상태(stateless)로 설계하자!

@Configuration과 싱글톤

- memberService() 호출 -> return new MemoryMemberRepository()
- orderService() 호출 -> return new MemoryMemberRepository()
- memberRepository() 호출 -> return new MemoryMemberRepository()
원래대로라면 MemoryMemberRepository 객체가 3개 새로 생성되어야 함.
하지만 스프링에서는 1개만 생성됨. -> 왜지?! -> (@Configuration이 자동으로 싱글톤보장)

@Configuration과 바이트코드 조작의 마법

원래대로라면 객체가 3개 생성되어야 하는데 그렇지가 않음. 스프링이 자바코드 자체를 어떻게 할수 있는것도 아니고 그럼 뭐지? -> 스프링은 클래스의 바이트코드를 조작하는 라이브러리를 사용해서 싱글톤을 보장한다.
—>@Configuration이 이 역할을 함.

AppConfig클래스도 스프링빈으로 등록이 된다.

AppConfig bean = ac.getBean(AppConfig.class);

System.*out*.println("bean = " + bean.getClass()); //bean의 클래스 이름은?
  • 출력결과 : bean = class hello.core.AppConfig$$EnhancerBySpringCGLIB$$203b18d9
  • 예상 결과 : class hello.core.AppConfig
    엥? 순수한 클래스라면 예상결과처럼 나와야 하는데 예상과는 다르게 클래스명 뒤에 xxxCGLIB가 붙음.
    내가 만든 클래스가 아니라 스프링이 CGLIB라는 바이트코드 조작 라이브러리를 사용하여 AppConfig를 상속받은 임의의 다른 클래스를 만든 것임. 그리고 그렇게 만든 것을 스프링 빈으로 등록함. (내가만든 순수한 AppConfig는 등록되지 않음.)

 

[AppConfig@CGLIB 예상 코드]

@Bean public 
MemberRepository memberRepository() {
	if (memoryMemberRepository가 이미 스프링 컨테이너에 등록되어 있으면?) { 
    		return 스프 링 컨테이너에서 찾아서 반환; } 
	else { //스프링 컨테이너에 없으면 기존 로직을 호출해서 MemoryMemberRepository를 생성하고 스프링 컨테이너에 등록 return 반환 } 
}

@Configuration을 적용하지 않고, @Bean만 적용하면 어떻게 될까?

-> MemoryMemberRepository3번 호출됨. 모두 새로운 객체가 생성됨.

  •  CGLIB기술없이 다시 순수한 AppConfig가 스프링빈에 등록됨.
  • bean = class hello.core.AppConfig

정리

@Bean만 사용해도 스프링빈으로 등록되지만, 싱글톤 보장은 안됨.
-> 스프링 설정 정보는 항상 @Configuration을 사용하자!