스프링의 생성자 주입이 필드 주입보다 권장되는 이유

스프링에서 한 클래스에 다른 클래스의 의존성을 부여하는 방법은 두 가지가 있다.

@Autowired 이용하기 (필드 주입)

package wooteco.helloworld.core;

...

@Component
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/users")
    public String retrieveUsers() {
        List<String> users = userService.findAll();
        return "found it";
    }

}

@AutoWired 어노테이션을 통해 UserController에 UserService를 의존 시켰다.

생성자 주입 이용하기

package wooteco.helloworld.core;

...

@Component
public class UserController {
    private final UserService userService;

    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/users")
    public String retrieveUsers() {
        List<String> users = userService.findAll();
        return "found it";
    }

}

어노테이션을 쓰는 대신 final로 필드를 선언하고 생성자를 통해 주입받도록 했다.

IntelliJ에서는 필드 주입으로 구현할 경우 생성자 주입으로 변경할 것을 제안하도록 되어 있다. 즉 후자가 더 나은 구현이라는 건데, 왜 그런 것일까?

final로 선언해 불변성을 보장할 수 있다

당연하게도 final은 생성자 주입 시에만 사용할 수 있다.

테스트가 쉬워진다

생성자를 통해 의존관계의 클래스를 주입받기 때문에 테스트하기가 용이하다.

순환의존을 막을 수 있다

간단히 말하자면, 필드 주입을 이용할 시 순환의존을 막을 수 없다.
컴파일 시 에러가 잡히지 않고 실행시에 스택 오버플로우를 일으키기 때문에 골치아프게 된다.

생성자 주입을 이용할 시에는 순환 의존을 시도할 시 BeanCurrentlyInCreationException이 발생하며 구동되지 않는다.

참고 자료

댓글 남기기