인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

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

yoon6669님의 프로필 이미지
yoon6669

작성한 질문수

스프링 핵심 원리 - 기본편

스프링 빈 조회 - 상속 관계

부모타입도 빈에 등록 되나요?

작성

·

37

·

수정됨

0

학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요.

1. 강의 내용과 관련된 질문을 남겨주세요.
2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요.
(자주 하는 질문 링크: https://bit.ly/3fX6ygx)
3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요.
(질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG)

질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요.
=========================================


강의 내용중에 부모타입으로 조회시 자식 빈까지 모두 조회된다 라는 부분에서 궁금한 점 있습니다.

 

강의에서 TestConfig 클래스에서 RateDiscountPolicyFixDiscountPolicy 타입을 빈으로 등록합니다.

그리고 이 두 타입을 모두 조회하기 위해서 ac.getBeansOfType(DiscountPolicy.class) 에 부모타입인 DiscountPolicy.class를 넣어 조회했습니다. 그리고 또 ac.getBeansOfType(Object.class) 을 하여 자식 타입을 모두 조회했습니다.
여기서 궁금한것은 DiscountPolicy나 Object 클래스는 Config 클래스에서 빈으로 따로 등록하지 않았는데도 어떻게 조회가 가능한건가요?

답변 1

0

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. yoon6669님

문의하신 내용은 스프링 컨테이너가 빈을 조회하는 방식과 자바의 객체 타입 시스템(상속 및 인터페이스 구현)이 결합되어 나타나는 동작입니다.

  1. 스프링 빈의 등록과 타입:

    • 스프링 컨테이너는 @Configuration 애노테이션이 붙은 설정 클래스에 정의된 @Bean 메서드를 호출하여 스프링 빈을 등록합니다.

    • @Bean 메서드의 반환 타입이 해당 스프링 빈의 타입이 됩니다.

    • 예를 들어, TestConfig 클래스에서 rateDiscountPolicy() 메서드는 RateDiscountPolicy 객체를 반환하고 fixDiscountPolicy() 메서드는 FixDiscountPolicy 객체를 반환합니다. 따라서 RateDiscountPolicyFixDiscountPolicy의 인스턴스가 스프링 빈으로 등록됩니다.

  2. 빈 조회 시 타입 매칭:

    • 스프링 컨테이너에서 ac.getBean(타입)이나 ac.getBeansOfType(타입)과 같이 타입으로 빈을 조회할 때, 스프링은 컨테이너에 등록된 빈들 중에서 요청한 타입과 호환되는 (assignable) 타입의 빈들을 모두 찾습니다.

    • 여기서 '호환된다'는 것은 요청한 타입이 등록된 빈의 실제 클래스의 부모 클래스이거나, 등록된 빈의 실제 클래스가 요청한 인터페이스를 구현한 경우 등을 포함합니다. 즉, 자바의 다형성이 적용됩니다. 부모 타입으로 조회하면 자식 타입도 함께 조회되는 것이 바로 이 때문입니다.

  3. DiscountPolicy.class로 조회 시:

    • TestConfig에서는 RateDiscountPolicy 빈과 FixDiscountPolicy 빈이 등록되었습니다.

    • RateDiscountPolicy 클래스와 FixDiscountPolicy 클래스는 모두 DiscountPolicy 인터페이스를 구현하고 있습니다 (소스 코드 상에는 직접적으로 구현 코드가 보이지 않지만, 맥락상 그렇다고 가정할 수 있습니다. 예:의 DiscountPolicy 인터페이스와의 RateDiscountPolicy 구현체).

    • 따라서 ac.getBeansOfType(DiscountPolicy.class)를 호출하면, 스프링은 DiscountPolicy 타입 또는 그 하위 타입(구현체)의 빈을 찾습니다. RateDiscountPolicyFixDiscountPolicyDiscountPolicy의 구현체이므로, 이 두 빈이 조회되는 것입니다. DiscountPolicy 자체는 추상화된 인터페이스일 뿐, 그 자체로 인스턴스화되어 빈으로 등록된 것은 아닙니다. 하지만 그 구현체들이 DiscountPolicy 타입으로 "호환"되기 때문에 조회 대상이 됩니다.

  4. Object.class로 조회 시:

    • 자바의 모든 클래스는 Object 클래스를 상속받습니다. Object는 모든 자바 객체의 최고 부모입니다.

    • 스프링 컨테이너에 등록된 모든 빈은 어떤 클래스의 인스턴스이든 결국 Object 타입을 상속받고 있습니다.

    • 따라서 ac.getBeansOfType(Object.class)를 호출하면, 스프링은 Object 타입 또는 그 하위 타입의 빈을 찾게 되는데, 이는 스프링 컨테이너에 등록된 모든 빈에 해당됩니다.

요약하자면, DiscountPolicyObject 클래스 자체가 빈으로 등록된 것이 아니라, 해당 인터페이스를 구현했거나 해당 클래스를 상속받은 자식 타입(구현체)의 빈들이 등록되어 있고, 스프링이 타입을 통해 빈을 조회할 때 요청된 타입과 호환되는 모든 빈을 반환하기 때문에 이러한 동작이 나타나는 것입니다.

추가로 자바는 instanceof, Class.isAssignableFrom 등의 기능을 통해서 다른 타입이 본인의 자식 타입인지 아닌지 인지할 수 있습니다.

감사합니다.

yoon6669님의 프로필 이미지
yoon6669
질문자

감사합니다! 그런데 1번 답변내용에 대해서 추가 질문 있습니다. 1번 답변에서

'스프링 컨테이너는 @Configuration 애노테이션이 붙은 설정 클래스에 정의된 @Bean 메서드를 호출하여 스프링 빈을 등록합니다.'

라고 설명해주셨는데요, 추후 @Configuration과 바이트코드 조작의 마법 강의에서 설명하시길 @Configuration을 붙이지 않아도 스프링 빈으로 등록된다고 하셨는데요. 물론 싱글톤을 보장하지 않는다는 차이점이 있지만요.

이 부분은 차치하고 제가 말하고 싶은 점은 스프링 빈으로 등록한다는 관점에서 보았을때 영한님의 이번 답변에서도 그렇고 초반 강의에서도 @Configuration 이 붙은 클래스에 @Bean 이 붙은 메서드를 스프링 빈으로 등록된다고 강의에서 말씀하신 것으로 기억나는데 추후 강의에서는 @Configuration이 붙지 않아도 스프링빈으로 등록된다고 하셔서 헷갈려서 질문드려봅니다.

초반부의 강의에서는 스프링빈 싱글톤에 대해서 배우지 않았고 싱글톤을 보장해준다는 의미에서 그렇게 말씀하신걸까요?

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. yoon6669님

@Configuration이 있든 없든 관계없이 @Bean이 있는 스프링 설정 클래스가 스프링 컨테이너에 등록되어야 @Bean의 내용이 작동해서 그 결과가 스프링 빈에 등록됩니다.

따라서 설정 클래스를 스프링 컨테이너에 먼저 등록해야 하는데요.

이때 등록하는 방법이 2가지가 있습니다.

  1. 스프링 컨테이너를 생성할 때 지정하는 방법

  2. 컴포넌트 스캔으로 인식하는 방법

만약 두 가지 방법을 모두 사용하지 않는다면 @Configuration이 있든 없든 관계없이 @Bean을 사용해도 스프링 컨테이너에 빈이 등록되지 않습니다. 왜냐하면 스프링이 해당 설정 클래스가 자체를 인식하지 않기 때문입니다.

감사합니다.

yoon6669님의 프로필 이미지
yoon6669

작성한 질문수

질문하기