JpaRepository 와 Bean 등록

LST·2022년 9월 3일
1

Spring Data Jpa 예제를 사용한 책들을 통해 공부를 하면 대부분 이렇게 사용을 한다.

// PostRepository.java
public interface PostRepository extends JpaRepository<Post, Long> {

}

// PostService.java
@RequiredArgsConstructor
@Service
public class PostService {
	private final PostRepository postRepository;
    ...
}

RequiredArgsConstructor 는 Lombok의 어노테이션으로 final로 선언된 변수로 생성자를 자동으로 만들어준다. 그리고 생성자가 한 개만 있을 때는 @Autowired 어노테이션을 생략할 수 있다. 하지만 JpaRepository를 상속받은 PostRepository를 빈으로 등록하는 부분은 어디에도 없지만 service에서는 생성자를 통해 빈을 주입받고 있다. @Controller 나 @Service 어노테이션을 따라가보면 @Component 어노테이션이 있다.

@Component 어노테이션이 있으면 컴포넌트 스캔을 통해서 자동으로 빈이 등록된다. 하지만 JpaRepository를 따라가봐도 빈을 등록하는 코드는 없었다.

JpaRepository가 상속받고 있는 NoRepositoryBean에는 @Service 나 @Controller와는 다르게 @Component 어노테이션이 없다. 그래서 검색을 해보니 답은 @EnableJpaRepository 어노테이션에 있었다.

@EnableJpaRepositories

@EnableJpaRepository 어노테이션은 Jpa Repository들을 활성화하기 위한 어노테이션인데 스프링에서는 @Configuration을 사용한 설정 클래스에서 @EnableJpaRepositories를 사용해야 하지만 스프링부트는 자동설정이 돼서 생략이 가능하다. 그리고 @EnableJpaRepositories 를 따라가 보면

import 를 통해서 JpaRepositoriesRegistrar 를 임포트 받고 있고 JpaRepositoriesRegistrar 는 이름만 봐도 JpaRepository를 빈으로 등록하는 역할을 한다는 것을 추측할 수 있다. 또한 RepositoryBeanDefinitionRegistrarSupport를 상속받고 있다. 이것은 importBeanDefinitionRegistrar의 구현체라고 볼 수 있는데 이 인터페이스는 BeanDefinition을 정의할 수 있는 특수한 형태의 인터페이스다. 여기부터는 metadata로 코드가 작성돼서 봐도 잘 모르겠다.

JpaRepository를 빈으로 등록하지도 않았는데 주입받을 수 있는 이유를 요약하자면

  • 스프링에서는 Configuration 클래스에 @EnableJpaRepositories를 사용하지만 스프링부트에서는 자동으로 등록이 된다.
  • 이 EnableRepositories는 JpaRepositoryRegistrar를 상속받는다.
  • JpaRepositoryRegistrar 는 importBeanDefinitionRegistrar의 구현체를 상속받는데 여기서 JpaRepository를 빈으로 등록한다.

0개의 댓글