스프링 컨테이너 (Spring Container)
스프링 컨테이너는 스프링 빈들을 생성 및 관리하며, 스프링 빈 간의 의존관계 주입을 대신 해 준다.
스프링 컨테이너는 스프링 코드 내에서 ApplicationContext 인터페이스의 구현체로 표현된다.
//Configuration 클래스로 스프링 컨테이너 생성
ApplicationContext acConfig = new AnnotationConfigApplicationContext(AppConfig.class);
//XML 파일로 스프링 컨테이너 생성
ApplicationContext acXml = new GenericXmlApplicationContext("appconfig.xml");
다음 예시 코드를 통해 스프링 컨테이너에서 빈이 등록되고 의존관계가 설정되는 과정을 살펴보자.
@Configuration
public class AppConfig{
@Bean
public ExampleService exampleService(){
return new ExampleService(
ExampleRepository(),
ExamplePolicy()));
}
@Bean
public ExampleRepository exampleRepository(){
//ExampleRepository는 인터페이스임
//DBExampleRepository는 이 인터페이스의 특정 구체 클래스
return new DBExampleRepository();
}
@Bean
public ExamplePolicy examplePolicy(){
//마찬가지로 ExamplePolicy는 인터페이스
return new FixedExamplePolicy();
}
}
우선 AppConfig 클래스를 통해 BeanDefinition을 생성하고, 각 빈들을 스프링 컨테이너에 등록한다.
이 때 등록되는 스프링 빈들은 모두 싱글톤 객체로써 저장된다. 여러 다른 사용자들이 동시에 빈을 조회해도 이들은 모두 같은 객체를 가리키게 된다.
기본적으로 빈 이름은 메소드 이름으로 등록된다. 만약 다른 이름을 쓰고 싶다면 다음과 같이 작성한다.
@Bean(name="beanNameExample")
위 코드에서 나타나는 의존성은 다음과 같다.
[exampleService → exampleRepository], [exampleService → examplePolicy]
스프링 빈 조회
스프링 컨테이너에서 스프링 빈은 다음과 같은 방법들로 조회할 수 있다.
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
//빈 이름으로 조회
ExampleService exampleService = ac.getBean("exampleService", ExampleService.class);
//빈 타입으로 조회
ExampleRepository exampleRepository = ac.getBean(ExampleRepository.class);
//구체 타입으로 조회 (유연성 낮음)
DBExampleRepository dbExampleRepository = ac.getBean("exampleRepository", DBExampleRepository.class);
동일한 타입이 둘 이상 존재하는 경우
스프링 빈을 타입으로 조회 시, 동일 타입의 스프링 빈이 둘 이상 존재하면 오류가 발생한다.
이 경우 빈 이름을 지정해 특정 빈만 조회하도록 하여 오류를 피할 수 있다.
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
//빈 타입으로 조회
//이 때 ExampleRepository 타입의 빈이 둘 이상이면 오류 발생
//ExampleRepository exampleRepository = ac.getBean(ExampleRepository.class);
//빈 이름을 부여해 하나의 빈만 조회하도록 수정
ExampleRepository exampleRepository = ac.getBean("repository1", ExampleRepository.class);
특정 타입의 빈을 모두 조회하기
ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
void findAllBeanByType(){
Map<String, ExampleRepository> result = ac.getBeansOfType(ExampleRepository.class);
}
ExampleRepository는 인터페이스임에 유의하자.
즉, 위 코드는 스프링 컨테이너에 등록된 ExampleRepository 인터페이스를 구현한 클래스 빈들을 조회한다.
이 때, 상위 클래스 타입으로 조회하면 하위 클래스 타입도 함께 조회된다. 즉, 최상위 클래스인 Object 타입으로 조회하면 모든 스프링 빈을 조회할 수 있다.
BeanFactory
BeanFactory는 스프링 컨테이너의 최상위 인터페이스로, 스프링 빈을 관리하고 조회하는 역할을 담당한다.
위 코드에서 사용했던 getBean() 메소드 역시 BeanFactory에서 제공한다.
ApplicationContext 와의 차이
ApplicationContext가 더 하위 인터페이스이기 때문에, ApplicationContext는 BeanFactory의 기능들과 함께 부가적인 여러 기능들을 제공한다.
부가적인 기능으로는 메시지 소스, 환경변수, 이벤트, 리소스 조회 등이 있다.
Reference
인프런 : 스프링 핵심 원리 - 기본편
'Framework > Spring' 카테고리의 다른 글
[Spring] 스프링 빈 (Spring Bean) (0) | 2021.04.01 |
---|---|
[Spring] 의존성 주입 (DI, Dependency Injection) (0) | 2021.03.10 |