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

pansakr님의 프로필 이미지

작성한 질문수

스프링 핵심 원리 - 기본편

인터페이스 타입 변수에 인터페이스가 담길 수 있나요?

해결된 질문

작성

·

101

0

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

@Test
@DisplayName("애플리케이션 빈 출력하기")
void findApplicationBean(){
    String[] beanDefinitionNames = ac.getBeanDefinitionNames();
    for (String beanDefinitionName : beanDefinitionNames) {

        // 이부분 질문
        BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);

        //이하 생략..
  }
}

스프링 빈 중에서 애플리케이션 빈만 출력하는 예제입니다

 

BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);

 

위 코드에서 변수 beanDefinition 의 타입인 BeanDefinition는 인터페이스니까

ac.getBeanDefinition(beanDefinitionName)의 리턴 타입이 BeanDefinition의 구현체일 줄 알았는데

 

매서드를 따라가보니 제일 상위에서 map.get()이 리턴되는데 그 값이 구현체가 아닌

BeanDefinition인터페이스 자체가 리턴되더라구요

 

Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

BeanDefinition bd = beanDefinitionMap.get(String beanName)

bd 가 리턴되게 되어있음

 

즉 BeanDefinition 인터페이스 타입인 bd가 메서드를 타고 내려오면서 질문한 부분인

BeanDefinition beanDefinition 에 담기게 되는 걸로 확인이 되었는데

인터페이스에 구현체가 아닌 인터페이스가 담길 수 있나요?

 

아니면 제가 뭔가 잘못 알고있거나 잘못 확인한 걸까요?

답변 2

1

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

디버깅 해보시면 아래와 같이 여러가지의 BeanDefinition 구현체가 beanDefinitionMap에 담겨있는 걸 확인할 수 있습니다.

image

감사합니다.

0

안녕하세요, 인프런 AI 인턴입니다.

pansakr님께서 문의하신 내용은 AnnotationConfigApplicationContextgetBeanDefinition 메서드 호출 시 반환되는 객체의 타입에 대한 질문으로 이해됩니다. 질문 주신 내용에서 BeanDefinition 타입의 객체가 어떻게 인터페이스 타입으로 반환될 수 있는지에 대한 혼동이 있는 것 같습니다.

먼저, BeanDefinition은 인터페이스입니다. 스프링 프레임워크에서는 이 인터페이스를 여러 클래스가 구현하고 있습니다. 예를 들어, RootBeanDefinition, ScannedGenericBeanDefinition 등이 이에 해당합니다. getBeanDefinition(String beanName) 메서드는 실제로는 BeanDefinition 인터페이스의 구현체를 반환합니다. 여기서 중요한 점은, beanDefinitionMapString을 키로, BeanDefinition 인터페이스의 구현체를 값으로 가지고 있다는 것입니다. 따라서, beanDefinitionMap.get(beanName)을 통해 반환받는 객체는 BeanDefinition 인터페이스를 구현한 어떤 클래스 객체일 것입니다.

BeanDefinition 인터페이스 타입의 변수에 구현체가 담기는 것은 자바에서 다형성의 일반적인 원리에 부합합니다. 인터페이스 타입으로 선언된 변수는 그 인터페이스를 구현한 어떤 클래스의 인스턴스도 참조할 수 있습니다. 이는 인터페이스가 하나의 계약이나 규격을 제공하고, 구현체가 그 규격을 실제로 구현한다는 점에서 출발합니다. 프로그래밍에서 이런 방식을 통해 높은 수준의 추상화와 유연성을 확보할 수 있습니다.

ac.getBeanDefinition(beanDefinitionName) 호출이 BeanDefinition 인터페이스를 반환한다고 보기보다는, 사실상 BeanDefinition 인터페이스를 구현한 어떠한 클래스의 인스턴스를 반환하는 것이며, 이를 BeanDefinition 타입의 변수에 할당하게 됩니다. 바로 이 점이 객체 지향 프로그래밍의 다형성을 활용하는 예시 중 하나입니다.

즉, BeanDefinition beanDefinition이라는 표현은 구현체를 담는데 문제가 없으며, 이는 자바의 다형성 원칙에 기반한 것입니다.

사실 관련하여 확인하고자 하시는 자세한 부분이 있다면, 아래 링크가 도움이 될 것 같습니다.
- AnnotationConfigApplicationContext 다형성

// 예시 코드
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);

여기서 getBeanDefinition 메서드는 BeanDefinition 인터페이스의 구현체를 반환하며, 이를 인터페이스 타입 변수에 담는 것이 가능합니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

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

beanDefinitionMapString을 키로, BeanDefinition 인터페이스의 구현체를 값으로 가지고 있다고 하셨는데요

실제 코드를 확인해 봤더니 Map<String, BeanDefinition> beanDefinitionMap 으로

인터페이스의 구현체가 아닌 인터페이스 자체를 가지고 있었습니다.

 

그러면 beanDefinitionMap.get()의 결과는 BeanDefinition 인터페이스의 구현체가 아닌

BeanDefinition 인터페이스 자체가 되는것이 아닌가요?

 

그리고 beanDefinitionMap.get()의 값이 결국 메서드를 타면서 최종적으로 리턴되어지는데

그렇게 되면 위에 질문드렸던 것 처럼 BeanDefinition타입 변수에 인터페이스가 들어가게 되는것 같습니다.

 

연결된 메서드들 중 어느 부분에서 BeanDefinition의 구현체를 생성해 리턴하는지 알려주시면

이해해 도움이 될 것 같습니다.

 

사실 이 부분은 강의 진행에 큰 영향은 없는 부분 같지만, 찾다보니 궁금해서 질문드렸습니다..

pansakr님의 프로필 이미지

작성한 질문수

질문하기