스프링에서 한 클래스에 다른 클래스의 의존성을 부여하는 방법은 두 가지가 있다.
@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
이 발생하며 구동되지 않는다.
참고 자료
- 생성자 주입을 @Autowired를 사용하는 필드 주입보다 권장하는 하는 이유
https://madplay.github.io/post/why-constructor-injection-is-better-than-field-injection
Comments powered by Disqus.