• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

MemberServiceV3_3을 @Autowired로 필드 주입을 할 수 있는 이유

23.06.01 13:36 작성 23.06.01 13:56 수정 조회수 352

0

package hello.jdbc.service;
@SpringBootTest
class MemberServiceV3_3Test { //테스트에서는 Public 없어도 됨

    @Autowired
    MemberRepositoryV3 memberRepository;
    @Autowired
    MemberServiceV3_3 memberService;

    @TestConfiguration
    static class TestConfig {

       @Bean
       DataSource dataSource() {
           return new DriverManagerDataSource(URL, USERNAME, PASSWORD);
       }
       @Bean
       PlatformTransactionManager transactionManager() {
           return new DataSourceTransactionManager(dataSource());
       }
       @Bean
       MemberRepositoryV3 memberRepositoryV3() {
           return new MemberRepositoryV3(dataSource());
       }
       @Bean
       MemberServiceV3_3 memberServiceV3_3() {
           return new MemberServiceV3_3(memberRepositoryV3());
       }
}

여기서 @SpringBootTest를 사용하면 @SpringBootApplication 안에 있는 @ComponentScan을 사용한다고 알고 있습니다.

그리고 test의 package 위치가 hello.jdbc.service이므로hello.jdbc.service를 포함한 그 하위 패키지는 컴포넌트 스캔의 대상이 됩니다.

(hello.jdbc.service 에는 MemberServiceV1 ~ V3_3 이 있습니다)

 

(1) 여기까지 맞게 생각한건지 궁금합니다.

(2) 컴포넌트 스캔의 대상인 class인 MemberServiceV3_3Test를 스프링 컨테이너에 넣고

@Autowired  MemberServiceV3_3 memberService;

를 하면 MemberServiceV3_3 타입의 빈을 조회해야하는데 MemberServiceV3_3클래스에는 @Configuration나 @Component가 없습니다.

서비스뿐만 아니라 MemberRepositoryV0 ~ V3 클래스도 전부 다 없습니다.

근데 어떻게 memberRepository,memberService 필드에 의존관계주입을 줄 수있는건가요?

등록된 MemberRepositoryV3타입이나 MemberServiceV3_3타입의 빈이 없는데??

 

(3)

@SpringBootTest가 있으면 해당 테스트 클래스는 특수하게 @Autowired를 허용해준다고 하는 데 이 허용안에는 MemberRepositoryV3 memberRepository;를 자동으로 빈으로 생성해주는 것도 포함되어 있는 건가요??

(4)

아니면 @TestConfiguration가 먼저 실행이되어 빈으로 생성이 되는 건가요??

강의 자료에서는

@TestConfiguration : 
테스트 안에서 내부 설정 클래스를 만들어서 사용하면서 이 에노테이션을 붙이면, 
스프링 부트가 자동으로 만들어주는 빈들에 추가로 필요한 스프링 빈들을 등록하고 테스트를 수행할 수 있다

라고 이미 자동으로 만들어주는 빈들에 추가로 만들어준다 라고 되있던데....

스프링 핵심원리 - 다양한 의존관계편을 보고 구글링을 해봐도 잘 모르겠네요...

 

질문이 많아 죄송합니다

답변주시면 정말 감사하겠습니다.

답변 1

답변을 작성해보세요.

1

y2gcoder님의 프로필

y2gcoder

2023.06.02

안녕하세요, 코딩먹는하마 님. 공식 서포터즈 y2gcoder 입니다.

어떻게 보면 스프링 핵심 원리 - 기본편에 어울리는 질문인 것 같습니다 ㅎㅎ

하나씩 답변드려보겠습니다!

(1) @SpringBootTest를 쓰면 기본적으로는 @SpringBootApplication이 선언된 클래스를 찾아서 스프링 부트 애플리케이션을 실행합니다. 그러나 애플리케이션 클래스를 찾지 못했을 경우에는 테스트 클래스의 패키지를 시작으로 컴포넌트 스캔을 수행합니다. 이 때 basePackage 의 위치는 @SpringBootApplication 이 선언된 클래스 기준입니다! 그래서 예상하신 컴포넌트 스캔 대상이 다를 수는 있을 것 같습니다.

(2) 여기서 @Autowired가 가능한 이유는 @TestConfiguration에서 MemberServiceV3_3와 MemberRepositoryV3 빈을 명시적으로 등록했기 때문입니다. @Autowired 애노테이션은 스프링 컨테이너에서 해당 타입의 빈을 찾아서 의존성을 주입해주는 역할을 합니다. 이때 스프링 컨테이너는 @Component, @Service, @Repository, @Controller 등의 애노테이션을 포함한 클래스 뿐만 아니라 @Configuration에서 @Bean 애노테이션을 통해 등록된 빈들도 참조합니다. 따라서 MemberServiceV3_3와 MemberRepositoryV3 클래스에는 @Service, @Component 등의 애노테이션이 없지만, @TestConfiguration에서 @Bean을 통해 스프링 컨테이너에 등록되었으므로 @Autowired를 사용할 수 있는 것입니다.

(3) @SpringBootTest 애노테이션 자체는 MemberRepositoryV3를 빈으로 자동 생성해주는 기능은 없습니다. @SpringBootTest는 스프링 부트 애플리케이션을 테스트 환경에서 실행하기 위한 애노테이션입니다. 스프링 부트 애플리케이션을 실행하면 @ComponentScan이 동작하여 @Component, @Service, @Repository, @Controller 등의 애노테이션이 선언된 클래스를 빈으로 등록하고, @Autowired 애노테이션을 통해 의존성을 주입합니다. 하지만 MemberRepositoryV3 클래스에는 이러한 애노테이션이 선언되어 있지 않으므로 @Autowired를 통해 의존성을 주입받기 위해서는 @TestConfiguration에서 @Bean 애노테이션을 통해 스프링 컨테이너에 빈으로 등록해야 합니다.

(4) @TestConfiguration은 테스트 환경에서만 동작하는 @Configuration입니다. 이 애노테이션을 통해 @Bean 애노테이션을 사용하여 필요한 빈들을 추가적으로 등록할 수 있습니다. 테스트를 실행할 때 @SpringBootTest는 먼저 스프링 부트 애플리케이션을 실행하고, 그 후에 @TestConfiguration이 동작하여 빈들을 추가로 등록합니다. 따라서 테스트를 수행하는 동안에는 MemberServiceV3_3와 MemberRepositoryV3가 스프링 컨테이너에 빈으로 등록되어 있어 @Autowired를 통해 의존성을 주입받을 수 있습니다.


감사합니다.

와우... 좋은 답변 정말 감사합니다. 많은 도움됐습니다 :)

y2gcoder님의 프로필

y2gcoder

2023.06.02

파이팅입니다!

인프런님의 프로필

인프런

2024.02.02

추가적인 질문이 있습니다. 지금 테스트코드에서는 TestConfig를 통해 빈을 등록해가지고 memberRepository와 memberService 주입받고 테스트를 실행하면 해당 메서드가 @Transactional이 붙어있기에 프록시 객체까지 생성이 된건 잘 이해된것 같습니다.

 

그런데 테스트코드가 아닌 실제 애플리케이션을 돌리면 현재 따로 Component관련 어노테이션도 안붙였고 Config에 빈등록도 안했기때문에 실제로는 정상적으로 실행이 안되겠죠?

y2gcoder님의 프로필

y2gcoder

2024.02.02

저 코드들은 테스트 패키지에서 작성했기 때문에 실제 애플리케이션 영역에 영향을 주지 않는 것이 맞습니다.

만약 애플리케이션 실행시 src/main/java 를 기준으로 각 빈들을 생성 후 의존성 주입을 하는 과정에서 의존성 주입을 해야 할 빈이 등록되지 않았다면 말씀하신 것처럼 에러를 뱉을 것입니다 :)

인프런님의 프로필

인프런

2024.02.02

뒤에서 그부분에 대해서 설명하시네요 ㅎㅎ 감사합니다!