지난 시간에 이어서 스프링 컨테이너와 스프링 빈에 대해 알아볼 것이다.
TIL 진짜 거의 다 썼는데 글이 다 날라갔다...😢
앞으로 임시저장 믿고 까불지 말고, 출간하기 버튼을 누르자😬 (아니면 다른 곳에다가도 저장해두자,,)
지난 시간에 getBean
메서드를 이용해서 이름/타입으로 빈을 조회하는 방법에 대해 알아보았다.
그러면 여기서 질문! DiscountPolicy
를 조회하면 어떻게 될까?
바로 DiscountPolicy
와 FixDiscountPolicy
, RateDiscountPolicy
까지 조회된다.
이러한 결과가 나오는 이유는 스프링 빈이 상속 관계를 가지기 때문이다.
부모 타입으로 조회하면 자식 타입도 함께 조회되기 때문에, DiscountPolicy
으로 조회하면 DiscountPolicy
의 자식인 FixDiscountPolicy
, RateDiscountPolicy
까지 조회되는 것이다.
😮: 오잉 근데 DiscountPolicy
는 인터페이스이고, FixDiscountPolicy
, RateDiscountPolicy
는 구현체인데 그래도 부모라고 하는 건가요?
👩🏻🏫: 맞습니다. 다형성과 계층구조 관점에서보면 DiscountPolicy
도 FixDiscountPolicy
, RateDiscountPolicy
의 부모라고 합니다.
💡 인터페이스, 추상 클래스, 클래스 모두 부모가 될 수 있다.
✔ 인터페이스(interface
): 모든 메서드의 구현 없음, 다중 상속 가능, 객체 인스턴스화 불가능
✔ 추상 클래스(Abstract class
): 일부 메서드의 구현 없음, 객체 인스턴스화 불가능
✔ 구체 클래스(class
): 모든 메서드가 구현되어 있음, 객체 인스턴스화 가능
아래의 그림처럼 부모 타입을 조회하면 자기 자신과, 자신을 상속하는 하위 빈까지 모두 조회된다.
위의 그림에서의 1번처럼 자바 객체에서 최고 부모 Object
타입이 있다.
Object
타입을 조회하면, 모든 스프링 빈을 조회하게 된다.
🔗 코드 확인하기
지난 시간에 스프링 컨테이너를 엄밀하게 말하면 BeanFactory
와 ApplicationContext
로 구분한다고 했다.
BeanFactory
와 ApplicationContext
가 무엇이 다른지 한 번 알아보자.
getBean()
등 우리가 지금까지 사용했던 대부분의 기능을 제공한다.BeanFactory
를 상속받는다.ApplicationContext
의 기능 = BeanFactory
의 기능 + 다양한 부가 기능MessageSource
(메시지 소스를 활용한 국제화기능)EnvironmentCapable
(환경변수)ApplicationEventPublisher
(애플리케이션 이벤트)ResourceLoader
(편리한 리소스 조회)
ApplicationContext
는 스프링 관리뿐만 아니라 위의 4가지 기능 등 다양한 부가적인 기능까지 제공하므로BeanFactory
를 직접 사용하기 보다는ApplicationContext
를 사용한다!
스프링 컨테이너는 다양한 형식의 설정 정보를 받아들일 수 있도록 유연하게 설계되었다.
지금까지는 애노테이션 기반 자바 코드 설정을 사용해왔다.
최근에는 스프링 부트를 많이 사용하면서 XML
기반의 설정은 잘 사용하지 않지만, XML
을 사용하면 컴파일 없이 빈 설정 정보를 변경할 수 있다는 장점이 있으므로 XML
을 이용한 방법도 알아보자!
🔗 코드 확인하기
→ XML
기반의 appConfig.xml
파일과 자바 코드로 된 AppConfig.java
파일을 비교해보면 거의 비슷하다!
스프링은 어떻게 자바, XML, Groovy 등 다양한 설정 형식 방식을 지원할 수 있는 것일까?
바로 BeanDefinition
인터페이스 덕분이다!
(사진의 오른쪽 아래처럼) 다양한 방식으로 만들어진 설정 정보를 전달받아서 BeanDefinition
을 만들게 된다.
스프링 컨테이너는 BeanDefinition
을 이용해서 스프링 빈을 생성한다.
그러니까 스프링 컨테이너는 어떤 형식으로 만들었는지를 전~혀~ 알 필요가 없다. 왜❓ BeanDefinition
만 가져오면 되니까!
이것도 역시 계속 강조해왔던 역할과 구현의 분리, 즉 DIP
원리를 지켜왔기 때문이다!
BeanDefinition
에 대해 더 알아보자.
BeanDefinition
은 빈 설정 메타정보라고 하며, 자바에서는 @Bean
, XML에서는 <bean>
이 부여된 정보별로 메타 정보를 생성한다.
스프링 컨테이너는 이 메타정보를 기반으로 스프링 빈을 생성한다.
🔗 코드 확인하기
실무에서 BeanDefinition
을 직접 정의해서 사용하는 경우는 흔하지 않으므로, 더 깊게 배우는 것은 생략하겠다!
스프링은 알면 알수록 정말 편리한 기능을 많이 제공하는 것 같다.