지난 시간에 ApplicationContext
를 스프링 컨테이너라고 부른다고 했다.
이번 섹션에서는 이 스프링 컨테이너가 생성되는 과정에 대해 알아볼 것이다.
ApplicationContext.java
파일을 통해서도 알 수 있듯이 ApplicationContext
는 인터페이스이다.XML
을 기반으로 만드는 방법과 애노테이션 기반의 자바 설정 클래스로 만드는 방법, 이렇게 두 가지가 있다.XML
으로 잘 만들지 않고 애노테이션 기반의 자바 설정 클래스로 만든다.왜일까 ❓
XML
설정에 대한 부담이 있고, 프로젝트 규모가 커지면 유지보수성이 낮아지게 된다!
💡 스프링 컨테이너
엄밀히 따지자면 스프링 컨테이너를
BeanFactory
,ApplicationContext
로 분리해서 불러야 한다. 하지만BeanFactory
를 직접 사용하는 경우는 거의 없어서 보통ApplicationContext
를 스프링 컨테이너라고 한다.
빈 이름 →
key
, 빈 객체 →value
스프링 컨테이너를 생성할 때 구성 정보를 지정해줘야해서 AppConfig.class
를 구성 정보로 지정해주었다.
전달받은 구성 정보, AppConfig
을 사용해서 스프링 빈을 등록한다.
오른쪽의 빈 이름
은 구성 정보의 메서드 이름을 사용하는데, 다른 이름으로 지정하고 싶으면 원하는 이름으로 설정해도 된다.
단, 이름을 중복으로 하면 에러가 발생하므로 괜히 나중에 고생하지 말고 처음 정할 때부터 잘 정하자😵
이제 스프링 컨테이너는 설정 관계를 참고해서 의존관계를 주입(DI
)해준다.
📌 참고
지금까지 스프링은 빈을 생성하고, 의존관계를 주입하는 단계가 있는데 사실은 이해를 돕기 위해 이렇게 나눈 것이다.
자바 코드로 스프링을 등록하면 생성자를 호출하면서 의존관계 주입도 처리된다.
AppliccationContextInfoTest.java
파일을 만들어서 컨테이너에 등록된 모든 빈을 조회해보자.
@Test
@DisplayName("모든 빈 출력하기")
void findAllBean() {
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name = " + beanDefinitionName + "object = " + bean);
}
}
📌 모든 빈 조회하기
ac.getBeanDefinitionNames()
: 스프링에 등록된 모든 빈 이름 조회ac.getBean(Bean 이름)
:Bean 이름
을 인자로 넘겨서 빈 객체(인스턴스) 조회
실행해보면 이렇게 모든 빈이 조회된다.
그런데 사실 내가 등록한 빈은 memberServiceobject
부터 discountPolicyobject
까지다.
그 위에 출력되는 것들은 스프링의 기능을 위해 생성된 것들이다.
그래서 만약 내가 만든 빈만 출력하고 싶다면 다음과 같이 작성해보자!
@Test
@DisplayName("애플리케이션 빈 출력하기")
void findApplicationBean() {
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
//Role ROLE_APPLICATION: 직접 등록한 애플리케이션 빈
//Role ROLE_INFRASTRUCTURE: 스프링이 내부에서 사용하는 빈
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("name = " + beanDefinitionName + "object = " + bean);
}
}
}
📌 어플리케이션 빈 조회하기
ROLE_APPLICATION
: 직접 등록한 어플리케이션 빈ROLE_INFRASTRUCTURE
: 스프링이 내부에서 사용하는 빈
실행하면 다음과 같이 출력된다.
💡 스프링 컨테이너 스프링 빈을 찾는 가장 기본적인 방법
getBean(Bean이름, 타입)
getBean(타입)
내가 찾고자 하는 빈이 없다면 예외가 발생한다.
NoSuchBeanDefinitionException: No bean named 'xxxxx' available
🔗 코드 확인하기
위에서 스프링 빈을 타입에 따라 조회하는 방법인 getBean(타입)
에 대해 알아보았다.
만약 동일한 타입의 스프링 빈이 두 개 이상이라면?
NoUniqueBeanDefinitionException
예외가 발생한다!
해결법은 간단하다.
📌 해결 방법
- 빈 이름을 지정해준다.
- 해당 타입에 해당하는 빈을 모두 조회하고 싶은 것이라면,
ac.getBeansOfType(타입)
을 사용하면 예외가 발생하지 않는다.
🔗 코드 확인하기
오늘 밤에 마저 합시다..