1. 스프링 컨테이너
스프링 컨테이너는 자바 객체의 생명 주기를 관리하며 생성된 자바 객체들에게 추가적인 기능을 제공한다. 스프링에서는 자바 객체를 빈이라고 부르기 때문에 스프링 컨테이너는 내부에 존재하는 빈의 생명주기를 관리하며 생성된 빈에게 추가적인 기능을 제공하는 것이다. xml, 어노테이션 기반의 자바 설정 클래스로 만들 수 있으며 스프링 부트가 등장하면서 대부분 사용하지 않게 되었다.
의존성 주입을 통해 애플리케이션의 컴포넌트를 관리할 수 있으며 서로 다른 빈을 연결하여 애플리케이션 빈을 연결하는 역할을 한다.
2. 스프링 컨테이너 구성 인터페이스
스프링 컨테이너는 Beanfactory 와 ApplicationContext 두 종류의 인터페이스로 구현되어 있다.
3. 스프링 컨테이너 생성 과정
자바의 어노테이션 기능 or xml 방식
자바 방식
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(AppConfig.class);
xml 기반 구성 메타데이터의 기본 구조
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<bean id="..." class="...">
<!-- collaborators and configuration for this bean go here -->
</bean>
<!-- more bean definitions go here -->
</beans>
xml 방식 컨테이너 생성
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
4. 컨테이너에 등록된 모든 빈 조회
package hello.core.bean;
import hello.core.Appconfig;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
class ApplicationContextInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Appconfig.class);
@Test
@DisplayName("모든 빈 출력하기")
void findAllbean(){
//alt + enter하면 반환형에 맞는 자료형, 변수 넣어줍니다.
//ac 컨테이너 안에 들어있는 빈들의 모든 이름을 String에 넣습니다.
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
//iter 를 입력 후 tab키를 누르면 자동으로 for문이 만들어집니다.
for (String beanDefinitionName : beanDefinitionNames) {
//정의된 이름을 하나하나 꺼내면서 bean이라는 Object자료형을 가진 변수에 넣어줍니다.
Object bean = ac.getBean(beanDefinitionName);
//출력
System.out.println("name = " + beanDefinitionName + "object = " + bean);
}
}
@Test
@DisplayName("애플리케이션 빈 출력하기")
void findApplicationBean(){
//마찬가지로 정의된 빈의 이름들을 가져옵니다.
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
//BeanDefinition 자료형을 반환합니다.
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);
}
}
}
}
5. 스프링 빈을 조회하는 기본적인 방법
ac.getBean(빈이름, 타입);
ac.getBean(타입);
조회 대상이 없다면 예외를 발생시킨다
6. 동일한 타입이 둘 이상일 때 스프링 빈 조회하는 방법
package hello.core.bean;
import hello.core.member.Member;
import hello.core.member.MemberRepository;
import hello.core.member.MemoryMemberRepository;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
class ApplicationContextSameBeanFindTest {
//밑의 설정을 컨테이너에 등록해줍니다.
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
//테스트 파일 안에서만 사용할 것.
@Configuration
static class SameBeanConfig{
@Bean
public MemberRepository memberRepository1(){
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository2(){
return new MemoryMemberRepository();
}
}
//같은 타입이 둘 이상 있으면 오류를 발생.
@Test
@DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 중복 오류가 발생한다")
void findBeanByTypeDuplicate(){
//ac.getBean(MemberRepository.class)를 하면 오류가 발생
//그냥 조회하면 밑과같은 오류(NoUniqueBeanDefinitionException)가 뜨므로 해당 오류를 넣어서 테스트를 완료한다.
Assertions.assertThrows(NoUniqueBeanDefinitionException.class,
() -> ac.getBean(MemberRepository.class));
}
@Test
@DisplayName("특정 타입을 모두 조회하기")
void findBeanByType(){
//Alt + Enter 애용!!
Map<String, MemberRepository> beansOfType = ac.getBeansOfType(MemberRepository.class);
//iter + tab키
for (String key : beansOfType.keySet()) {
System.out.println("key = " + key + "value = " + beansOfType.get(key));
}
System.out.println("beansOfType = " + beansOfType);
org.assertj.core.api.Assertions.assertThat(beansOfType.size()).isEqualTo(2);
}
}
7. 스프링 빈 설정 메타 정보는 BeanDefinition 이라는 추상화를 통해 구현
'[ Development ] > [ Back-end ] Spring 기본' 카테고리의 다른 글
[Spring 스프링 기본] 의존관계 자동 주입 (0) | 2023.12.26 |
---|---|
[Spring 스프링 기본] 컴포넌트 스캔 (1) | 2023.12.05 |
[Spring 스프링 기본] 싱글톤 컨테이너 (1) | 2023.11.28 |
[Spring 스프링 기본] 객체 지향 원리 적용 (0) | 2023.11.14 |
[Spring 스프링 기본] 2. 핵심 원리 이해 1 - 예제 만들기 (0) | 2023.11.07 |
[Spring 스프링 기본] 1. 객체지향설계와 스프링 (0) | 2023.10.22 |
[Spring 스프링 입문] JPA, AOP (0) | 2023.10.17 |