ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
여기서 ApplicationContext는 인터페이스인데, 스프링 컨테이너라고 한다.
스프링 컨테이너는 애너테이션 기반의 자바 설정 클래스(AppConfig.class)로 만들 수도 있고, XML 기반으로도 만들 수 있다. XML기반으로는 잘 사용하지 않는다.
스프링 컨테이너를 얘기할 때, BeanFactory와 ApplicationContext로 구분해서 얘기하는데, BeanFactory는 스프링 컨테이너의 최상위 인터페이스로 스프링 빈을 관리하고 조회하는 역할을 담당한다.(getBean() 제공)
ApplicationContext는 BeanFactory를 상속받은 인터페이스인데, 빈을 관리하는 기능 + 편리한 부가 기능을 제공한다. (MessageSource, EnvironmentCapable, ApplicationEventPublisher, ResourceLoader)
그림과 같이 @Configuration으로 지정된 설정 클래스 안에서 @Bean이 붙은 매서드를 찾아 실행하면서 스프링 빈을 등록한다.
이 때, 빈 이름은 @Bean(name="빈 이름") 이렇게 직접 부여할 수 있지만, 디폴트로는 매서드 이름을 사용한다. 빈 이름은 항상 다른 이름을 부여해야 한다.(중요)
의존관계 자동 주입에 대해서는 나중에 추가하기
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class); // @Test @DisplayName("애플리케이션 빈 출력하기") void findApplicationBean() { String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames(); for (String beanDefinitionName : beanDefinitionNames) { BeanDefinition beanDefinition = applicationContext.getBeanDefinition(beanDefinitionName); // //Role ROLE_APPLICATION: 직접 등록한 애플리케이션 빈 //Role ROLE_INFRASTRUCTURE: 스프링이 내부에서 사용하는 빈 if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) { Object bean = applicationContext.getBean(beanDefinitionName); System.out.println("name=" + beanDefinitionName + " object=" + bean); } } }
- applicationContext.getBeanDefinitionNames() : 스프링 빈에 등록된 모든 빈 이름을 반환한다.
- applicationContext.getBeanDefinition(beanDefinitionName) : 빈 이름으로 빈에 대한 정보를 반환한다.
- applicationContext.getBean(beanDefinitionName) : 빈 이름으로 빈 객체를 반환한다.
- beanDefinition.getRole() : 빈의 정보 중 역할을 반환한다.
- BeanDefinition.ROLE_INFRASTRUCTURE : 스프링 내부에서 등록해 사용하는 빈
스프링 컨테이너에 등록된 빈을 조회하는 방법
- applicationContext.getBean(빈이름, 타입)
MemberService memberService = applicationContext.getBean("memberService", MemberService.class);
- applicationContext.getBean(타입)
MemberService memberService = applicationContext.getBean(MemberService.class);
- applicationContext.getBeansOfType()
Map<String, MemberRepository> beansOfType = applicationContext.getBeansOfType(MemberRepository.class);
출력하면
스프링 빈은 부모 타입으로 조회하면 자식 타입도 함께 조회된다. 따라서, 자바 객체의 최상위에 있는 Object 타입으로 조회하면 모든 스프링 빈이 조회된다.
스프링이 XML과 자바 설정 클래스 이 두 가지 방법을 이용하여 컨테이너를 설정할 수 있도록 하는 데에는 BeanDefinition이라는 추상화가 중심에 있다.
BeanDefinition이 어떤 설정 형식을 읽어서 만들어지면 이 안에는 빈 설정 메타정보가 들어있다. 스프링 컨테이너는 이 메타정보를 통해 스프링 빈을 생성한다.
- BeanClassName : 생성할 빈의 클래스 명(자바 설정 처럼 팩토리 역할의 빈을 사용하면 없음)
- factoryBeanName : 팩토리 역할의 빈을 사용할 경우 이름, 예) appConfig
- factoryMethodName : 빈을 생성할 팩토리 메서드 지정, 예) memberService
- Scope : 싱글톤(기본값)
- lazyInit : 스프링 컨테이너를 생성할 때 빈을 생성하는 것이 아니라, 실제 빈을 사용할 때 까지 최대한
생성을 지연처리 하는지 여부- InitMethodName : 빈을 생성하고, 의존관계를 적용한 뒤에 호출되는 초기화 메서드 명
- DestroyMethodName : 빈의 생명주기가 끝나서 제거하기 직전에 호출되는 메서드 명
- Constructor arguments, Properties : 의존관계 주입에서 사용한다. (자바 설정 처럼 팩토리 역할의
빈을 사용하면 없음)
**참고 : 스프링 핵심 원리 - 기본편(김영한)
의존관계 자동주입에 대해서는 나중에 추가하기