@Binds는 @Provides의 특수한 형태일 뿐이며, @Provides와 같은 역할을 한다. 다른 점은 Binds에는 여러 제약이 있고, 제약이 많은 만큼 코드를 덜 생성한다는 점이다. 지금부터 @Binds에 어떠한 제약이 있는지 어떤 경우에 사용이 되어야 하는지 살펴보자.
@Binds
@Binds는 하나의 객체를 변수로 받아 해당 변수를 생성(생성자 주입)하고 프로퍼티, 메서드까지 @Inject가 붙은 모든 주입을 처리하고 나서 반환하는 Annotation이다. @Binds는 @Provides와 같은 역할을 하지만, @Provides에 비해 많은 제약이 있어 코드를 덜 생성한다.
@Binds를 쓰기 위한 조건으로는 두 개의 필수적인 조건이 있다.
- @Binds는 추상(abstract) 클래스의 추상(abstract) 메서드에 붙이는 것만 유효하다.
- @Binds가 붙은 메서드는 반드시 하나의 매개 변수만을 가져야 한다.
또한 다음과 같은 특징이 있다.
- 추상 클래스에서 구현되어야 하므로, 추상 클래스에 Provider을 넣으려면 static 한 companion object에서만 넣을 수 있다.
- 인자로 받는 값을 Provide로 제공받지 않아도 생성자 주입을 통해 생성 된다.
- 인자로 받는 값의 타입이 아닌 인자로 받는 값이 구현하는 다른 타입으로 return 타입을 만들어야 한다. 같은 타이븡로 반환되면 주입이 무한 반복되는 cycle이 생기기 때문이다. (리턴 값이 다시 인자로 주입)
즉, @Binds는 다음과 같이 작성 가능하다.
@Module
abstract class PersonModule {
@Binds
abstract fun providesStudentWithName(student: Student) : Person
companion object{
@Provides
fun providesString() = "StudentA"
}
}
@Binds 예제
예제5에서 @Binds가 어떻게 처리되는지 자세히 다루어보자.
예제 링크 : https://github.com/seyoungcho2/Dagger2Example
예제5의 구조는 다음과 같다.
*컴포넌트
@Component(modules = [PersonModule::class])
interface SchoolComponent{
fun getStudent() : Student
}
*모듈
@Module
abstract class PersonModule {
@Binds
abstract fun providesStudentWithName(student: Student) : Person
companion object{
@Provides
fun providesString() = "StudentA"
}
}
*Person Interface
interface Person {
fun getPersonName() : String
}
*Student Class
class Student @Inject constructor() : Person {
@Inject
lateinit var name: String
override fun getPersonName() = name
}
이제 이 클래스들을 바탕으로 코드를 RunExample.kt에서 실행한다.
fun main(){
val personComponent : SchoolComponent = DaggerSchoolComponent.create()
val student : Person = personComponent.getStudent()
println(student.getPersonName()) // StudentA
}
위 실행코드는 <그림2>의 과정으로 처리된다.
- Binding을 시작한다.
- Binds의 Student 인자는 Student Class의 생성자 주입에 의해 생성된다.
- Student의 내부 프로퍼티인 name에 Inject하기 위해 Provider에서 String을 생성한다.
- Provider에서 생성된 String을 Student에 Inject한 후 Student는 Person으로 형변환된다.
- Person에 Injection된다.
즉, 실제 실행 과정은 Provider와 다른게 없다. 다른 점은 여러 제약이 걸림으로써 처리해야할 부분이 많이 줄어들어 generation된 코드가 줄어든다는 점이다.
반응형