@AutoWired란?
스프링은 생성자 주입(Constructor Injection), 세터 주입(Setter Injection), 필드 주입(Field Injection) 이라 불리는 의존성을 주입하기 위한 세가지 방법을 제공한다. 그리고 이들은 @AutoWired란 어노테이션을 통해 주입된다. 지금부터 이 세가지 방법을 알아보자.
생성자 주입
생성자 주입을 하기 위해서는 생성자 함수 constructor가 필요하다. constructor 앞에 @Autowired를 사용함으로써 생성자 주입을 할 수 있다. 예를 들어 UserCreator이 UserRepository를 주입 받는다면 다음과 같이 작성이 가능하다.
@Component
class UserCreator @Autowired constructor(
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")
}
}
하지만, 우리가 지금까지 다뤘던 코드들은 위 코드 대신 다음과 같이 사용했다. 이유는 스프링 4.3 버전부터는 단일 생성자를 가진 클래스의 경우 @Autowired 어노테이션을 붙이지 않고도 의존성 주입이 가능하기 때문이다.
@Component
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")
}
}
필드 주입
필드 주입을 하기 위해서는 주입이 필요한 필드를 late init var로 선언한 후 위에 @Autowired를 써주면 된다. 가시성은 private으로 해도 괜찮다.
예를 들어 앞서 다룬 UserCreator과 같은 동작을 하면서 필드 주입을 사용하는 UserCreatorFieldInjection 클래스는 다음과 같이 만들 수 있다.
@Component
class UserCreatorFieldInjection() {
@Autowired
private lateinit var repository: UserRepository
fun createUserWithRandomId(user: String) {
val id = UUID.randomUUID().toString()
repository.createUser(id, user)
println("[User Creation Success] User $user id: $id")
}
}
lateinit var로 선언된 UserRepository위에 @Autowired가 붙은 것을 볼 수 있다. 이렇게 하면 필드 주입이 가능하다.
하지만, 필드 주입을 사용하면 테스트 코드 작성 시 UserRepository의 가시성을 public 하게 바꿔주거나 리플렉션을 사용하거나 하는 등 추가적으로 해야 하는 작업들이 생겨 때문에 불편하기 때문에 일반적으로 권장되지는 않는다.
세터 주입
세터 주입을 하기 위해서는 주입이 필요한 필드를 nullable 한 var로 설정하거나 lateinit var로 선언한 후에, setter 함수 위에 @Autowired를 써주면 된다.
예를 들어 앞서 다룬 UserCreator과 같은 동작을 하면서 필드 주입을 사용하는 UserCreatorFieldInjection 클래스는 다음과 같이 만들 수 있다.
@Component
class UserCreatorSetterInjection() {
private var repository: UserRepository? = null
fun createUserWithRandomId(user: String) {
val id = UUID.randomUUID().toString()
repository?.createUser(id, user)
println("[User Creation Success] User $user id: $id")
}
@Autowired
fun setRepository(repository: UserRepository) {
this.repository = repository
}
}
세터 주입은 선택적으로 주입이 필요한 상황이 있을 경우 사용하기 유용하다.
하지만 일반적으로는 생성자 주입만으로 충분하기 때문에 거의 사용되지 않는 주입 방식이다.
전체 코드: GitHub
이 프로젝트가 도움이 되셨다면 저장소에 Star⭐️를 눌러주세요! Stargazers는 다음 페이지에서 확인할 수 있습니다.