스프링 컨테이너와 스프링 빈
스프링 컨테이너
ApplicationContext를 스프링 컨테이너라 한다.
ApplicationContext는 인터페이스다.
- 스프링 컨테이너는 XML기반, 어노테이션 기반 설정 클래스로 만들 수 있다.
Appconfig가 어노테이션 기반 설정이었음.
스프링 컨테이너 생성과정
- 스프링 컨테이너 생성

- 스프링 컨테이너 생성시, 구성 정보 지정해줘야함.
-> 여기서는 AppConfig.class를 이용한 것.
-
스프링 빈 등록

-
스프링 빈 의존관계 설정

- 스프링 빈 의존관계 설정 - 완료

스프링 빈 조회
참고 : 빈 이름 == 함수 이름
-
이름으로 조회
ac.getBean("membserService", MemberService.class)
-
이름 없이 타입으로만 조회
ac.getBean(MemberService.class)
-
구체 타입으로 조회
ac.getBean("memberService", MemberServiceImpl.class)
-> 구체 타입으로 조회하면, 변경시의 유연성이 떨어진다.
언제 무얼 사용? -> 동일한 타입 둘 이상이면 이름으로 조회하기.
스프링 빈 조회 - 상속관계
부모 타입으로 조회하면, 자식 타입도 함께 조회됨.
그렇기에 모든 자바 객체 부모인 Object 조회하면 모든 스프링 빈 딸려나옴.

문제상황
이러한 사실에 근거한다면, 만약 ac.getBean(DiscountPolicy.class) 할 시 중복오류 날 것.
왜냐하면 rateDiscountPolicy, fixDiscountPolicy 두 개이기에, 뭘 꺼내야할지 모르기 때문.
어떻게 해결? -> 이 역시 이름 지정 해주면 됨.
ac.getBean("rateDiscountPolicy", DiscountPolicy.class)
BeanFactory 와 ApplicationContext
BeanFactory
- 스프링 컨테이너의 최상위 인터페이스
- 스프링 빈 관리, 조회 담당
- getBean() 제공
ApplicationContext
Q. 그럼 굳이 왜 상속받아서 쓸까?
애플리케이션 개발엔 빈 관리,조회 이상으로 더많은 기능이 필요하다.
ApplicationContext가 제공하는 부가기능

- 메시지소스 활용한 국제화 기능 : 예를들어 한국에서 들어오면 한국어, 영미권에서 들어오면 영어로 출력
- 환경변수 : 로컬, 개발, 운영등을 구분해서 처리
- 애플리케이션 이벤트 : 이벤트 발행하고 구독하는 모델을 편리하게 재원
- 편리한 리소스 조회 : 파일, 클래스패스, 외부 등에서 리소스 편리하게 조회
다양한 설정 형식 지원 - 자바 코드, XML
- 스프링 컨테이너는 다양한 형식 설정정보 모두 받아들일 수 있음.

어노테이션 기반 자바코드 설정
@Configuration, @Bean 등등 지금까지 한 방식
XML 설정
- 레거시 프로젝트에 아직 많은 방식
GenericXmlApplicationContext 를 사용하면서 xml 설정 파일을 넘김
ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml)

- 구조가 어노테이션 기반
Appconfig.class 랑 매우 흡사.
스프링 빈 설정 메타 정보 - BeanDefinition
앞서 다양한 설정 정보 모두 받아들일 수 있는 원리가 뭘까? -> BeanDefinition 이라는 추상화.
- 자바 코드를 읽어서 BeanDefinition 를 만든다.
- XML 읽어서 BeanDefinition 만든다.
BeanDefinition = 빈 설정 메타정보.
@Bean, <bean> 당 각각 하나의 메타 정보가 생성.
그리고 스프링 컨테이너는 이 메타정보를 기반으로 스프링 빈 생성.


AnnotationConfigApplicationContext 는 AnnotatedBeanDefinitionReader 를 사용해서
AppConfig.class 를 읽고 BeanDefinition 을 생성한다.
-> Reader가 읽어준 후, BeanDefinition 만드는 것.
BeanDefinition 안에 뭐가 들어있나
- BeanClassName : 생성할 빈의 클래스 명 ( 자바 설정 처럼 팩토리 역할 빈 사용하면 없음 )
- factoryBeanName : 팩토리 역할 빈 사용할 경우 이름. 예) appConfig
- factoryMethodName : 빈 생성할 팩토리 메서드 이름. 예) memberService
- Scope : 싱글톤
- lazyInit : 스프링 컨테이너 생성할 때 빈 생성이 아니라, 실제 빈 사용할 때 까지 최대한 생성 지연 처리할건지 여부
- InitMethodName : 빈 생성하고, 의존관게 적용한 뒤에 호출되는 초기화 메서드 명
- DestroyMethodName : 빈 생명주기 끝나서 제거하기 직전에 호출되는 메서드 명
- Constructor arguments, Properties : 의존관계 주입에서 사용. (자바 설정 처럼 팩토리 역할 빈 사용하면 없음 )
- BeanDefinition 직접 생성해서 컨테이너에 등록 가능하나, 실무에서 그럴 일 거의 없음.