인프런 커뮤니티 질문&답변

김민정님의 프로필 이미지
김민정

작성한 질문수

스프링 핵심 원리 - 기본편

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

@Configuration을 사용한 싱글톤

작성

·

493

5

안녕하세요! 김영한님과 서포터즈님들 항상 좋은 강의와 질문답변 감사합니다! :)

 

강의를 듣고 관련된 질문들을 찾아보면서 궁금한게 있는데요,

@Configuration을 사용하면 스프링 컨테이너에서 해당 인스턴스가 존재하는지를 확인하고 있으면 인스턴스 반환, 없으면 생성하는 기능으로 싱글톤이 보장된다는것을 알겠습니다.

@Congfiguration 없이는 싱글톤 보장이 안된다고하셨는데

https://www.inflearn.com/questions/288987

의 질문답변을 보면 @Congfiguration의 유무에 관계 없이 싱글톤으로 유지된다는 답변을 봐서

뭐가 맞는건지 궁금해서 질문드립니다. 

 

그리고 

@Configuration 없이 생성된 memberRepository 세개의 인스턴스들에 대해서 

@Bean이 붙은 memberRepository객체는 스프링이 관리해주는 스프링 빈이고

나머지 MemberServiceImpl, OrderServiceImpl 의 memberRepository는 스프링 빈이 아닌거죠?

 

감사합니다~

 

답변 2

3

안녕하세요. 김민정님, 공식 서포터즈 David입니다.

1. @Congfiguration의 유무에 관계 없이 싱글톤으로 유지

@Configuration이 아닌 @Component가 붙은 곳에서의 @Bean이 붙은 객체 생성 메서드는 스프링 컨테이너에 의해 최초 호출시 반환되는 객체가 빈으로 등록되고 싱글톤으로 관리됩니다. 최초 호출 이후 @Bean이 붙었던 메서드를 또 실행하면 그때는 객체를 새롭게 생성해서 반환되며 해당 객체는 스프링 컨테이너에 의해 싱글톤으로 관리되는 객체가 아닙니다. 따라서 최초 호출에 의해 생성된 객체가 빈으로 등록되고 싱글톤으로 관리되기 때문에 위와 같이 말씀하신 것 같습니다.

2. @Congfiguration 없이는 싱글톤 보장이 안된다고하셨는데

1번에서 설명드린 걸 토대로 생각해보면, @Configuration 없이는 싱글톤이 보장되지 않음은 최초 호출 이후 호출된 객체 생성 메서드의 반환 값을 살펴보면 알 수 있습니다. 최초 호출 객체 생성 메서드 반환 객체는 빈으로 등록, 최초 호출 이후 객체 생성 메서드 호출 반환 객체는 컨테이너에 등록없이 새롭게 생성된 객체를 반환됩니다. 그렇기 때문에 동일한 객체 생성 메서드의 반환 값이 @Configuration 없이는 매번 같은 객체를 반환하지 못합니다. 만약 @Configuration이 붙었다면 최초 호출 이후 호출되는 것은 프록시를 타고 스프링 컨테이너를 먼저 살핀 뒤 빈이 존재하면 해당 빈을 반환하게 될 것입니다.

3. @Bean이 붙은 memberRepository 객체~

@Baen이 붙은 memberRepository 메서드가 최초로 호출되고 생성된 객체는 빈으로 등록되어 싱글톤으로 관리되고, 이후에 호출되어 반환되는 모든 객체는 일반 객체입니다.

감사합니다.

안녕하세요!
작성해주신 답변과 질문 속 링크 내용을 보고 헷갈리는 점이 생겨서 질문 드립니다.

1번 답변에서

최초 호출 이후 @Bean이 붙었던 메서드를 또 실행하면 그때는 객체를 새롭게 생성해서 반환되며 해당 객체는 스프링 컨테이너에 의해 싱글톤으로 관리되는 객체가 아닙니다.

라고 하신 부분에서
'@Bean이 붙었던 메서드를 또 실행'한다는 부분이 헷갈리는데,

이유는

@Test
@DisplayName("스프링 컨테이너와 싱글톤")
void singletonContainer() {

	// 스프링 컨테이너 생성(싱글톤 컨테이너)
	ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

	 // 호출1
	MemberService memberService1 = ac.getBean("memberService", MemberService.class);
	// 호출2
	MemberService memberService2 = ac.getBean("memberService", MemberService.class);

	// 조회할 때마다 같은 객체를 반환하는지(참조값이 같은지) 확인 
	System.out.println("memberService1 : " + memberService1);
	System.out.println("memberService2 : " + memberService2);

	// memberService1 == memberService2
	assertThat(memberService1).isSameAs(memberService2);

위 코드에서
호출1, 호출2가 '@Bean이 붙었던 메서드를 또 실행'하는 것이 아닌가요..?

@configuration과 바이트코드 조작의 마법에서
@Configuration 미적용 시 싱글톤 유지가 안되는 이유는

AppConfig에서

@Bean    
public MemberService memberService() {
        System.out.println("call AppConfig.memberService");
        return new MemberServiceImpl(memberRepository());
}

위 코드처럼 memberRepository()new MemberReposiroty()를 실행하는
순수 자바 메서드 호출 코드 때문에 객체가 새로 생성되서 반환되기 때문인 것으로 이해했습니다.

그래서 @Configuration을 적용하면
순수 자바 코드로 인해 객체가 새로 생성되는 것을 막고(싱글톤 보장),

@Bean이 붙은 메서드를 호출하는 것은
@Configuration 유무 관계없이 스프링 컨테이너에 의해 싱글톤이 보장된다고 이해했습니다.

혹시, 제가 이해한 부분이 잘못된 것일까요,,

  1. 호출1, 호출2는 @Bean이 붙은 메서드를 실행하는 게 아니라, 컨테이너에서 해당 이름을 가진 빈을 찾아오는 것입니다.

  2. @Bean이 붙은 메서드를 (최초) 호출할 때 반환되는 객체가 빈으로 등록되어 싱글톤이 보장됩니다. @Configuration이 없다면 @Bean이 붙은 메서드를 (재차) 호출할 때 반환되는 객체가 컨테이너에 싱글톤 빈으로 등록된 것임을 보장하지 않습니다.

답변 주셔서 감사합니다!
덕분에 잘못 이해했던 부분을 바로잡을 수 있었습니다

0

김민정님의 프로필 이미지
김민정
질문자

아 그럼

링크 속 싱글톤 보장에 대해서는@Bean이 붙은 최초 호출의 빈들에 한해서 스프링 빈으로 등록되고 싱글톤유지가 된다는거고

 

그 다음 이후의 만들어지는 객체들은 @Configuration없이는 매번 새롭게 객체가 생성되서 싱글톤 유지가 안된다는 말씀이셨군요!

 

덕분에 더 자세히 배웠습니다!! 감사합니다~

김민정님의 프로필 이미지
김민정

작성한 질문수

질문하기