왜 빈을 조회할때, 자식까지 전부 조회하는가?

고동현·2024년 3월 28일
0

Spring

목록 보기
2/7

스프링 빈을 조회할때, 상속관계에서,
부모타입을 조회하면, 자식타입도 함께 조회를 한다.
그래서 이런글도 작성하였었다.
스프링 빈 컨테이너 작성글

처음에 빈 컨테이너에 대해서 공부할때, 부모타입을 통해서 자식타입도 함께 조사하는것에 대해서 기능적인 부분을 공부했었다.

이 내용은 내가 작성한 글을 보면 되겠다.

근데 궁금점이, 아 기능은 뭔지 알겠는데, 도대체 왜 빈을 조회할때, 그 해당 type의 class만 조회하면 되지 왜 자식 class까지 다 뒤져서 조회를 하는걸까? 라는 궁금증이 들었다.

구글링을하여도, 그냥 부모를 조회할때, 자식까지 조회하는게 대원칙이라는 말만 있을 뿐, 도대체 왜그래야하는지, 또 실제로 진짜 그렇게 구현해놨는지는 찾을 수 가 없었다.

우선, 이렇게 Spring이 부모 타입으로 조회하면, 해당 타입의 모든 자식 타입의 인스턴스도 함께 조회되는 이유는 Spring의 타입 기반 조회방식 때문이다.

이렇게 Type기준으로 빈을관리하며, 이때 type 계층을 고려한다.
따라서 특정 타입으로 빈을 조회할때, 그 타입을 상속받거나 구현한 모든 클래스의 인스턴스도 조회 대상이 된다.

이렇게 하면 좋은점은

  1. 타입을 기준으로 객체를 조회하면, 컴파일 타임에 타입 체크를 수행할수 있다.
  2. 인터페이스나 추상 클래스를 기준으로 객체를 조회하고 사용하면, 구현체를 쉽게 교체할 수 있다.
  3. 리팩토리 용이: 타입 기반으로 코드 작성시, 나중에 구현체를 변경하거나 리팩토링 할때도 영향을 받는 부분이 적어진다.

이런 장점들 때문에 Type계층으로 나누고 부모Type을 조회하면 자식class랑 구현체 전부 다 튀어나오는 것이다.

그런데 궁금한게 진짜 그렇게 구현이 되어있나? 싶었다.
코드 해석하기가 나름 어려웠는데 시간이 좀 걸렸다.

getBeansOfType 메서드는 일단 DefaultListableBeanFactory 클래스에 있다.

그래서 getbean 매서드로 가봤다.

여기서 신기하게 그 스프링 빈 컨테이너 작성글에서 보면,
부모타입으로 getBean을 했는데 구현클래스가 2개인경우 NoUniqueBeanDefinitionException이 터졌는것을 기억할 수 있을것다.


만약 DiscountPolicy bean = ac.getBean(DiscountPolicy.class); 이렇게 조회를 하려고 가정을했다면,=>현재 DiscountPolicy가 인터페이스 구현체로 FixDiscountPolicy,RateDiscountPolicy가 있다고 가정

getBean으로 가보자, 여기서 class requiredType에 DiscountPolicy가 들어갈 것이다. 그러면 resolveBean을 이 DiscountPolicy가 들어갈 것이다.


resolveBean으로 다시 가면,
여기서 이제 다시 resolveNamedBean으로 가야한다.

여기서 또 보면, 뭐 Assert.notNull이런걸로 type null이면 안된다 이런 오류도 보여주지만,
핵심적으로 candidateNames.length가 있는것을 볼 수 있다.

이부분에서, 자식 클래스가 2개 이상이면 1보다 크다는 뜻이고
이 if문 마지막에

noUniqueAsNull이 아니면 NoUniqueBeanDefintionException을 던지는것을 확인 할 수 있었다.

내부에 정확한 로직은 이해할 수 없었지만,
1. 부모type으로 조회시 자식 class,와 구현 클래스까지 뒤지기 위해서

이런식으로 이터레이터를 돌면서 Map에다가 담았음을 확인하였고,
그리고
2. 만약 이 candidates가 1이상이고, getBean으로 조회시에 NoUniqueBeanDefinitionException을 던지는것까지 확인을 해보았다.

이를통해, 빈 컨테이너와 빈 조회에 대해서 더 자세히 알 수 있었다.

ps. 오류 지적은 매우 감사합니다. 더 알려주세요!

profile
항상 Why?[왜썻는지] What?[이를 통해 무엇을 얻었는지 생각하겠습니다.]

0개의 댓글