middlemoon
Spring - 스프링 컨테이너와 스프링 빈 본문
이번 시간은 스프링 컨테이너 생성부터 스프링은 어떤 구조로 이어지는지 만들어보는 시간을 갖을 계획이다.
ApplicationContext는 스프링컨테이너라고 말한다.
자세하게 말해 컨테이너란?
- 객체들을 담고있는 하나의 공간이라고 생각하면 될것 같다.
이 블로그는 김영한님 강의를 토대로 작성하였으니 참고용으로 봐주시면 좋을 것 같고, 기록용으로 남기기 위해 올렸다는 점 참고해주시면 감사하겠습니다.
여기서 @Bean을 어노테이션으로 추가해줄 때 밑의 코드처럼 스프링 컨테이너에 즉 객체를 담고있는 저장소에
빈 이름 - memberService / 빈 객체 MemberServiceImpl 이런형식으로 담기는 것을 알수 있다.
주의할것은 @Bean에 대한 이름은 항상 다른 이름을 부여해야한다는 뜻이다.
단순하고, 명확하게 이 부분을 잘 신경쓰면 좋을 것 같다.


* 스프링 컨테이너는 설정 정보를 참고해서 의존관계를 주입(DI)한다.
* 단순히 자바 코드를 호출하는 것 같지만, 차이가 있다. 이 차이는 뒤에 싱글톤 컨테이너에서 설명한다.
import hello.core.AppConfig;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
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("name = " + beanDefinitionName + " object = " + bean);
}
}
}
자, 이제 컨테이너에 등록된 빈을 조회가 잘 되어있는지 확인해보려고 한다.
우선 맨 위에 AppConfig 자바 파일을 Bean으로 등록해주는 과정을 거쳤다
그 다음 위에서는 @Test코드를 작성하여 모든 빈이 출력하게끔 해주었다.
1. AnnotationConfigApplicationContext에 대한 객체를 만들어준다.
2. 리스트로 나올 객체를 배열로 선언 후
3. name에는 key값 object에는 value값이 나오게끔 만든다.

그럼 아까 만들었던 memberService부터 시작해서 discountPolicy까지 한번에 성공적으로 테스트되는것을 볼 수 있다.

참고 : //Role ROLE_APPLICATION: 직접 등록한 애플리케이션 빈
//Role ROLE_INFRASTRUCTURE: 스프링이 내부에서 사용하는 빈
이번엔 Bean이름으로 조회를 해보자.

지금과 위의 차이가 있다면 위에는 Bean전체를 조회할수록 만들어준것이고
지금은 memberService라는 일부 Bean값만 가져와서 조회하는 화면이라고 볼수 있다. getBean()에 어떤것을 넣느냐에 따라
결과값이 달라지니 참고하면 좋을 것 같다.

Assertions를 통해 memberService가 MemberServiceImpl을 포함하고 있는지 판별하는 코드

assertThat을 통해 Type으로만 조회 getBean에서는 name이 안들어가 편리하게 적용할수 있다.

Bean 이름 조회가 실패되었을 때,
그 이후에는 테스트 코드 검증을 위해 Assertions.assertThrows() 를 사용해서 예외가 무조건 터질때 테스트 코드가 성공할수 있도록 하는 기능이다.

람다 표현식을 이용해 NoSuchBean에 대한 코드를 검증을 확인할 수 있게 된다.
그 다음, 내가 해볼 것은
"타입으로 조회시 같은 타입이 둘 이상 있으면, 중복 오류 발생"
public class ApplicationContextSameBeanFindTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);
@Test
@DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 중복 오류 발생")
void findBeanByTypeDuplicate(){
ac.getBean(MemberRepository.class);
}
@Configuration
static class SameBeanConfig{
@Bean
public MemberRepository memberRepository1(){
return new MemoryMemberRepository();
}
@Bean
public MemberRepository memberRepository2(){
return new MemoryMemberRepository();
}
}
}
본인이 만든 클래스를 보면 같은 형식의 다른클래스 @Bean기능을 하는 클래스가 존재한다.
이거를 조회해보고 싶어서 돌려보게 되면 에러가 뜨게된다. 왜냐하면 SamBeanConfig와 MemberRepository가 동시에 나오기때문에
Spring입장에서는 무엇을 써줘야하지? 라는 혼란이 오기때문이다.

친절하게 에러의 위치까지 알려준다.
그렇다면 어떻게 해결해야 되는지 알아보자.
중복 오류 발생하는 부분 한개와, 중복오류 발생 시 예외처리를 해주는 식을 만들어주면된다.(아래와 같이)

상속관계

보다시피 DiscountPolicy안에는 총 2가지의 rateDiscountPolicy(), fixDiscountPolicy()가 있다. 부모클래스안에 여러 자식클래스가 나오게 되면 테스트 코드에서는 실패를 나타내므로,
DiscountPolicy reateDiscountPolicy = ac.getBean("rateDiscountPolicy, DiscountPolicy.class);
이런식으로 구분해서 사용해주는 것이 좋다.
이 코드를 사용하고자 한다면
첫번 째, @Configuration을 선언 후
사용하고자 하는 클래스 기능들을 새롭게 만들어 준뒤, 스프링을 사용할 수 있는 AnnotationConfigApplicationContext(TestConfig.class)~
두번 째, @Test코드 작성
appConfig.xml

'Develop > Spring' 카테고리의 다른 글
| Spring - 컴포넌트 스캔 (0) | 2023.03.14 |
|---|---|
| Spring - 웹 에플리케이션과 싱글톤 (0) | 2023.03.05 |
| Spring - 스프링 핵심 원리 이해2 (객체 지향 원리 적용) (0) | 2023.02.06 |
| Spring - 스프링 핵심 원리 이해1 (0) | 2023.01.29 |
| Spring - 객체지향 프로그래밍의 이해 (0) | 2023.01.20 |