728x90
반응형
@Configuration 애노테이션을 이용하여 스프링 컨테이너를 생성하고 @Bean등록을 통해 스프링에 빈으로 등록할 클래스를 지정할 수 있다.
그리고 또 다른 클래스에서는 AnnotationConfigApplicationContext를 통해 스프링 컨테이너를 가져올 수 있다.
이거에 대한 글은 아래 글에 게시했었다.
https://wonsjung.tistory.com/359?category=1001976
오브젝트와 의존관계 - 5. 제어의 역전(IoC) / Spring's IoC
IoC라는 약자로 많이 사용되는 제어의 역전(Inversion of Control)이라는 용어가 있다. 제어권의 이전을 통한 제어관계 역전 제어의 역전이라는 건, 간단히 프로그램의 제어 흐름 구조가 뒤바뀌는 것이
wonsjung.tistory.com
이제 스프링 컨테이너에 등록된 빈을 조회하는 방법에 대해 알아본다.
- 모든 빈 출력하기
- 실행하면 스프링에 등록된 모든 빈 정보를 출력할 수 있다.
- ac.getBeanDefinitionNames() : 스프링에 등록된 모든 빈 이름을 조회한다.
- ac.getBean() : 빈 이름으로 빈 객체(인스턴스)를 조회한다.
- 애플리케이션 빈 출력하기
- 스프링이 내부에서 사용하는 빈은 제외하고, 내가 등록한 빈만 출력해보자.
- 스프링이 내부에서 사용하는 빈은 getBean()로 구분할 수 있다.
- ROLE_APPLICATION : 일반적으로 사용자가 정의한 빈
- ROLE_INFFRASTRUCTURE : 스프링이 내부에서 사용하는 빈
< 모든 빈 출력하기 코드 >
package com.example.demo.beanfind;
import com.example.demo.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;
public class ApplicationContextInfoTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("모든 빈 출력하기")
void findAllBean(){
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
Object bean = ac.getBean(beanDefinitionName);
System.out.println("beanDefinitionName = " + beanDefinitionName + "object = " + bean);
}
}
@Test
@DisplayName("애플리케이션 빈 출력하기")
void findApplicationBean(){
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
// getBeanDefinition -> bean 하나 하나에 대한 정보를 얻을 수 있다.
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
/***
getRole() -> bean의 역할을 알 수 있는 메서드
ROLE_APPLICATION : 내가 애플리케이션 개발을 위해 등록하였을 경우 해당한다.
ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈빈
**/
if(beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION){
Object bean = ac.getBean(beanDefinitionName);
System.out.println("beanDefinitionName = " + beanDefinitionName + "object = " + bean);
}
}
}
}
< 다양한 방법으로 빈 조회하기 >
package com.example.demo.beanfind;
import com.example.demo.AppConfig;
import com.example.demo.service.MemberService;
import com.example.demo.service.MemberServiceImpl;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;
public class ApplicationContextBasicTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("빈 이름으로 조회")
void findBeanByName(){
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
@Test
@DisplayName("이름 없이 타입으로 조회")
void findBeanByType(){
MemberService memberService = ac.getBean(MemberService.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
@Test
@DisplayName("구체 타입으로 조회")
void findBeanByName2(){
MemberService memberService = ac.getBean("memberService", MemberServiceImpl.class);
assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
}
@Test
@DisplayName("빈 이름으로 조회 실패시")
void findBeanByNameX(){
/**
* 존재하지 않는 빈 이름으로 조회 할 경우 오류가 발생한다. 이 때 테스트 코드 작성 요령
*/
assertThrows(NoSuchBeanDefinitionException.class,
() -> ac.getBean("xxxx", MemberService.class));
}
}
< 동일한 타입이 둘 이상일 경우 >
package com.example.demo.beanfind;
import com.example.demo.AppConfig;
import com.example.demo.discount.DiscountPolicy;
import com.example.demo.repository.MemberRepository;
import com.example.demo.repository.MemoryMemberRepository;
import com.example.demo.service.MemberService;
import org.assertj.core.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;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class ApplicationContextSameBeanFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
@Test
@DisplayName("타입으로 조회 시 같은 타입이 둘 이상 존재하면, 중복 오류 발생")
void findBeanByTypeDuplicate(){
assertThrows(NoUniqueBeanDefinitionException.class,
()->ac.getBean(MemberRepository.class));
}
@Test
@DisplayName("타입으로 조회 시 같은 타입이 둘 이상 있으면, 빈 이름을 지정하면 된다")
void findBeanByName(){
MemberRepository memberRepository = ac.getBean("memberRepository1", MemberRepository.class);
assertThat(memberRepository).isInstanceOf(MemberRepository.class);
}
@Test
@DisplayName("특정 타입 모두 조회하기")
void findAllBeanByType(){
Map<String, MemberRepository> beansOfType = ac.getBeansOfType(MemberRepository.class);
for (String key : beansOfType.keySet()) {
System.out.println("key = " + key + " value = " + beansOfType.get(key));
}
System.out.println("beansOfType = " + beansOfType);
assertThat(beansOfType.size()).isEqualTo(2);
}
@Configuration
static class SameBeanConfig{
@Bean
public MemberRepository memberRepository2(){
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository1(){
return new MemoryMemberRepository();
}
}
}
728x90
반응형
'Spring > Spring Core Basic' 카테고리의 다른 글
컴포넌트 스캔 (0) | 2022.03.17 |
---|---|
싱글톤 방식의 주의점 (0) | 2022.03.16 |
Intellij 수정사항 재실행 없이 확인하기 (0) | 2022.02.09 |
주문과 할인 도메인 설계 (0) | 2022.01.25 |
회원 도메인 실행과 테스트 (0) | 2022.01.21 |