[Spring] @Component와 @ComponentScan 사용해 자동으로 의존성 주입하기

2024. 11. 16. 07:41· Spring/Dependency Injection
목차
  1. @Bean 어노테이션 사용해 Bean 등록하기
  2. @Component 어노테이션 사용해 Bean 등록하기

@Bean 어노테이션 사용해 Bean 등록하기

이전 글에서 유저 정보를 조작하는 UserRepository 인터페이스를 구현하는 객체가 InMemoryUserRepository와 DbUserRepository 두개가 있고, 이 중 하나를 UserCreator 클래스에서 사용한다고 했을 때 코드를 다음과 같이 구성했었다.

interface UserRepository {
    fun createUser(id: String, user: String)
}

class InMemoryUserRepository(): UserRepository {
    override fun createUser(id: String, user: String) {
        println("User $user created with id: $id in InMemoryUserRepository")
    }
}

class DbUserRepository(): UserRepository {
    override fun createUser(id: String, user: String) {
        println("User $user created with id: $id in DbUserRepository")
    }
}
class UserCreator(private val repository: UserRepository) {
    fun createUserWithRandomId(user: String) {
        val id = UUID.randomUUID().toString()
        repository.createUser(id, user)
        println("[User Creation Success] User $user id: $id")
    }
}

 

그리고 Configuration 파일 내부에 @Bean 어노테이션을 사용해 Bean을 다음과 같이 구성했다.

@Configuration
class UserContainerConfiguration {
    @Primary
    @Bean
    fun inMemoryUserRepository(): UserRepository {
        return InMemoryUserRepository()
    }

    @Qualifier("dbUserRepository")
    @Bean
    fun dbUserRepository(): UserRepository {
        return DbUserRepository()
    }

    @Bean
    fun userCreator(@Qualifier("dbUserRepository") repository: UserRepository): UserCreator {
        return UserCreator(repository)
    }
}

 

하지만, 매번 이렇게 Configuration 파일 내부에 @Bean 어노테이션을 통해 Bean을 등록하는 것은 번거롭다.

Spring은 Bean을 더 편하게 등록하기 위한 방법을 제공하는데, 그 방법이 바로 @Component 어노테이션을 통해 Bean을 등록하는 방법이다. 지금부터 그 방법에 대해 알아보자.

 

@Component 어노테이션 사용해 Bean 등록하기

@Component를 통해 Bean을 등록하는 방법은 매우 간단하다. 단순히 각 클래스 위에 @Component를 붙이면 된다. 또한 만약 둘 이상의 구현체가 있을 때 붙이는 @Primary 어노테이션과 @Qualifier 어노테이션은 @Component 와 함께 붙이면 된다.

 

앞서 @Bean 어노테이션이 붙은 inMemoryUserRepository에 @Primary가 붙어있었고, dbUserRepository 위에 @Qualifier("dbUserRepository")가 붙어 있었으니 똑같이 @Component 위에 각 어노테이션을 붙이면 된다. 예를 들어 UserRepository 인터페이스를 구현하는 InMemoryUserRepository와 DbUserRepository는 다음과 같이 설정하면 된다.

package com.kotlinworld.spring.di.section6

..

interface UserRepository {
    fun createUser(id: String, user: String)
}

@Primary
@Component
class InMemoryUserRepository(): UserRepository {
    override fun createUser(id: String, user: String) {
        println("User $user created with id: $id in InMemoryUserRepository")
    }
}

@Qualifier("dbUserRepository")
@Component
class DbUserRepository(): UserRepository {
    override fun createUser(id: String, user: String) {
        println("User $user created with id: $id in DbUserRepository")
    }
}

 

마찬가지로 UserCreator 위에도 @Component를 붙이고, 생성자의 UserRepository 인자 앞에 @Qualifier("dbUserRepository")를 붙이면 DbUserRepository 객체가 주입된다.

package com.kotlinworld.spring.di.section6

..

@Component
class UserCreator(
    @Qualifier("dbUserRepository") private val repository: UserRepository
) {
    fun createUserWithRandomId(user: String) {
        val id = UUID.randomUUID().toString()
        repository.createUser(id, user)
        println("[User Creation Success] User $user id: $id")
    }
}

 

이후 UserContainerConfiguration을 모두 비우고 위에 @ComponentScan을 붙여 놓으면, UserContainerConfiguration 클래스가 있는 패키지와 하위의 모든 @Component Annotation이 붙은 클래스들이 스캔돼 Bean으로 등록된다.

package com.kotlinworld.spring.di.section6

..

@ComponentScan
@Configuration
class UserContainerConfiguration {

}

 

이제 각 Bean이 모두 제대로 등록됐는지 확인하기 위해 다음 코드를 실행해보자.

fun main(args: Array<String>) {
    val context = AnnotationConfigApplicationContext(UserContainerConfiguration::class.java)

    context.beanDefinitionNames.forEach { 
        println(it)
    }
}

 

그러면 다음과 같이 모든 Bean 들이 잘 등록된 것을 볼 수 있다.

 

마지막으로 UserCreator에 DbUserRepository가 제대로 등록됐는지도 확인해보자. 이를 위해 UserCreator Bean을 가져온다음 createUserWithRandomId 함수를 호출한다.

fun main(args: Array<String>) {
    val context = AnnotationConfigApplicationContext(UserContainerConfiguration::class.java)
    
    context.getBean(UserCreator::class.java).createUserWithRandomId("세영")
}

 

그러면 다음과 같은 로그가 나오는 것을 볼 수 있다. 유저 생성을 위해 DbUserRepository가 사용된 것을 볼 수 있다. 

 

여기까지 @Component와 @ComponentScan을 사용해 Bean을 등록하는 방법을 살펴봤다.

 

하지만 매번 @Bean 대신 @Component를 사용할 수 있는 것은 아니다. 이어서 어느 경우에 @Bean을 사용해야 하고 @Component를 사용해야 하는지 알아보자.

 

전체 코드: GitHub
이 프로젝트가 도움이 되셨다면 저장소에 Star⭐️를 눌러주세요! Stargazers는 다음 페이지에서 확인할 수 있습니다.
반응형
저작자표시 비영리 변경금지
  1. @Bean 어노테이션 사용해 Bean 등록하기
  2. @Component 어노테이션 사용해 Bean 등록하기


 

Kotlin, Android, Spring 사용자 오픈 카톡

오셔서 궁금한 점을 질문해보세요!
비밀번호 : kotlin22

open.kakao.com

'Spring/Dependency Injection' 카테고리의 다른 글
  • [Spring] @ComponentScan 사용해 특정 패키지 하위의 의존성을 스캔하는 방법 알아보기
  • [Spring] @Component와 @Bean의 차이는 무엇이고 언제 사용해야 할까?
  • [Spring] @Primary와 @Qualifier 사용해 하나의 인터페이스에 둘 이상의 구현체가 있을 때 의존성 주입 우선 순위 관리하기
  • [Spring] @Bean 사용해 클래스 초기화 시 의존성 주입하기
Dev.Cho
Dev.Cho
'조세영의 Kotlin World'는 Kotlin를 전문적으로 다루는 개인 기술 블로그입니다. Kotlin 세계에 대한 양질의 자료를 제공하며 Kotlin, Android, Spring, CI, CD 분야에 대해 다룹니다.
Dev.Cho
조세영의 Kotlin World
Dev.Cho
전체
오늘
어제

블로그 메뉴

  • LinkedIn
  • GitHub
  • 분류 전체보기 (491)
    • Kotlin (104)
      • Class and Interface (19)
      • Variable and Function (8)
      • Modifier (5)
      • Collection (14)
      • Time (8)
      • 동시성 제어 (7)
      • Reactive Programming (2)
      • Paradigm (2)
      • Kotlin 자료구조 (15)
      • Design Patterns (11)
      • Algorithm (3)
      • Exception (1)
      • 기타 (9)
      • Update History (0)
    • Coroutines (32)
      • Coroutine Basics (18)
      • Flow (9)
      • CoroutineScope (3)
      • Debugging (2)
    • Testing Codes (28)
      • Test 기본 (3)
      • JUnit5 (9)
      • MockK (6)
      • Testing Coroutines (1)
      • Testing Android (8)
      • Test 기타 (1)
    • Spring (50)
      • Dependency Injection (18)
      • Settings (5)
      • REST API (0)
      • DevTools (1)
      • MVC (18)
      • Error (2)
      • MongoDB (2)
      • Database (4)
    • Android (39)
      • Architecture (2)
      • Component (5)
      • Manifest (1)
      • Lifecycle (2)
      • Dependency Injection (17)
      • Resource (1)
      • Storage (1)
      • Security and Optimization (1)
      • WebView (2)
      • Error (6)
    • Android Jetpack Compose (33)
      • Compose (6)
      • Compose Modifier (13)
      • Compose Resource (4)
      • Compose State (4)
      • Compose Side Effect (6)
    • Android Jetpack Compose UI (48)
      • Compose Layout (14)
      • Compose Text (10)
      • Compose Button (5)
      • Compose Dialog (2)
      • Compose TextField (0)
      • Compose UIs (4)
      • Compose Animation (1)
      • Compose Canvas (12)
    • Android Jetpack (10)
      • Datastore (5)
      • ViewModel (4)
      • LiveData (1)
      • Paging (0)
    • KMP (5)
    • Programming (4)
    • Machine (9)
      • JVM (7)
      • Linux (2)
    • CI, CD (74)
      • Gradle (12)
      • Groovy Gradle (5)
      • Git (25)
      • Git Remote (5)
      • GitHub (5)
      • GitHub Actions (21)
    • Network (33)
      • GraphQL (12)
      • HTTP (11)
      • Basic (9)
    • 오픈소스 (3)
    • Database (3)
      • MongoDB (3)
    • IDE (6)
      • Android Studio (2)
      • Intellij (4)
    • Firebase (1)
    • Javascript (9)

공지사항

  • 코틀린 코루틴 완전 정복 강의 in 인프런 오픈
  • 코틀린 코루틴의 정석 책 출간
  • Kotlin Coroutines 공식 기술 문서 한국어 번⋯
  • GitHub에서 조세영의 Kotlin World를 Foll⋯
  • 문의&제안

인기 글

태그

  • dagger2
  • compose
  • junit
  • 안드로이드
  • junit5
  • 스프링
  • github actions
  • Unit Testing
  • flow
  • Kotlin
  • junit4
  • Class
  • 유닛 테스팅
  • gradle
  • kotlin spring
  • Spring boot
  • Android Compose
  • GraphQL
  • github
  • Jetpack Compose
  • Spring
  • GIT
  • 코틀린
  • java
  • Android
  • Dependency Injection
  • HTTP
  • 의존성 주입
  • Coroutine
  • 코루틴

최근 글

hELLO · Designed By 정상우.v4.3.0
Dev.Cho
[Spring] @Component와 @ComponentScan 사용해 자동으로 의존성 주입하기
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.