Image
Android/Dependency Injection

[Dagger2] 5. @Named Annotation을 이용한 Provider 구분

같은 타입의 Provider가 있을때 구분

앞서 Provider을 이용해 주입(Inject)가 되는 것을 보았다. 하지만, Provider만 사용하여 주입하는 것에는 문제점이 있다.

바로 Provider에서 제공(Provide)하는 인스턴스의 타입이 같을 때 어떤 인스턴스를 주입해야 하는지 모른다는 것이다.

 

예를 들어 아래와 같은 Module이 있다고 해보자.

@Module
class PersonModule {
    @Provides
    fun providesStudentName(): String = "StudentA"

    @Provides
    fun providesTeacherName(): String = "TeacherB"
}

 

이 모듈에서 제공하는 두가지 Provider의 반환 타입은 모두 String이다. 이 때 String 값을 아래 Student Class의 인스턴스에서 주입받고자 할 경우 어떤 Provider에서 주입 받아야 하는지 알 수 없다.

class Student() {
    @Inject
    lateinit var name: String
}

 

이를 그림으로 표현하면 다음과 같다.

그림1. 같은 타입을 제공하는 Provider

Person Module 내에 같은 타입을 반환하는 Provider가 있어 주입 시 어떤 Provider을 주입시켜야 하는지 모르는 것이다.

 

 

@Named Annotation을 이용한 같은 타입 Provider 구분

이를 해결하기 위해서는 @Named Annotation을 활용한다. @Named Annotation은 같은 타입 클래스의 인스턴스를 제공하는 Provider가 두 개 이상 있을 때 그 둘을 구분해주는 역할을 한다.

 

제공하는 쪽(Provider)과 주입 당하는쪽(Inject) 모두에 @Named Annotation을 사용해야 구분이 되므로 둘 모두에다가 @Named Annotation을 붙여야 구분이 주입이 가능해진다.

 

위의 <그림1>을 <그림2>와 같이 바꾸면 Student에는 Student 이름의 주입이 가능해진다.

그림2. @Named Annotation 적용

제공(Provider)하는 쪽의 fun과 주입받은 Student 에 모두 @Named 를 붙임으로써 Student가 어떤 Provider로부터 name 프로퍼티를 주입 받아야 하는지가 명확해졌다.

 

예제4에서 이에 대해 다루도록 한다. 먼저 예제4의 파일 구조는 다음과 같다.

예제 링크 : https://github.com/seyoungcho2/Dagger2Example

그림2. 예제4 파일 구조

@Component(modules = [PersonModule::class])
interface SchoolComponent{
    fun injectStudent(student: Student)
    fun injectTeacher(teacher: Teacher)
}
@Module
class PersonModule {
    @Provides
    @Named("Student")
    fun providesStudentName() = "StudentA"

    @Provides
    @Named("Teacher")
    fun providesTeacherName() = "TeacherB"
}

PersonModule에는 두개의 프로바이더가 있으며 각각은 @Named로 구분 된다.

 

class Student() {
    @Inject
    @Named("Student")
    lateinit var name: String
}
class Teacher {
    @Inject
    @Named("Teacher")
    lateinit var name: String
}

데이터를 담는 클래스인 Student와 Teacher은 각각 var name : String을 프로퍼티로 가지고 있으며 @Named로 어떤 프로바이더에 의해 주입받아야 하는지를 명시한다.

 

 

*RunExample.kt 파일

fun main(){
    val personComponent : SchoolComponent = DaggerSchoolComponent.create()
    val student = Student()
    personComponent.injectStudent(student)
    println(student.name) // StudentA

    val teacher = Teacher()
    personComponent.injectTeacher(teacher)
    println(teacher.name) // TeacherB
}

자 이제 Student와 Teacher의 인스턴스를 만들고 주입을 시작한다. 그러면 각각 @Named에 의해 자신이 주입 받아야 하는 인스턴스를 주입 받게 된다.

 

따라서 name 프로퍼티의 출력값은 Student는 StudentA가 되고 Teacher은 TeacherB가 된다.

 

반응형

 

이 글의 저작권은 '조세영의 Kotlin World' 에 있습니다. 글, 이미지 무단 재배포 및 변경을 금지합니다.

 

 

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

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

open.kakao.com