Spring은 @Autowired 어노테이션을 이용한 다양한 의존성 주입(Dependency Injection) 방법을 제공합니다.
의존성 주입은 필요한 객체를 직접 생성하는 것이 아닌 외부로부터 객체를 받아 사용하는 것입니다.
이를 통해 객체간의 결합도를 줄이고 코드의 재활용성을 높일 수 있습니다. @Autowired는 Spring에게 의존성을 주입하는 지시자 역할로 사용됩니다.
public class MemberController {
private final MemberService memberService;
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
클래스의 생성자가 하나이고, 그 생성자로 주입받을 객체가 빈으로 등록되어 있다면 @Autowired를 생략할 수 있다.
public class MemberController {
@Autowired
private MemberService memberService;
}
필드에 @Autowired 어노테이션만 붙여주면 자동으로 의존성이 주입된다.
하지만, 외부에서 변경하기 힘들다는 점과 프레임워크에 의존적이고 객체 지향적으로 좋지 않다는 단점이 있다.
public class MemberController {
private MemberService memberService;
@Autowired
public void setMemberService(MemberService memberService) {
this.memberService = memberService;
}
}
Setter 메서드에 @Autowired를 붙이는 방법이다.
수정자 주입을 사용하면 setter 메서드를 public으로 설정해야 하므로 언제 어디서든 변경이 가능하다.
과거에는 필드 주입과 수정자 주입을 많이 사용했다고 한다. 그러나 Spring을 포함한 대부분의 프레임워크에서는 방법은 생성자를 통한 주입을 권장한다.
개발을 하다 보면 여러 컴포넌트 간에 의존성이 생긴다. 그중에서도 A가 B를 참조하고, B가 다시 A를 참조하는 순환 참조가 발생하는 코드가 있다고 가정해 봅시다.
@Service
public class MadPlayService {
private final MadLifeService madLifeService;
public MadPlayService(MadLifeService madLifeService) {
this.madLifeService = madLifeService;
}
}
@Service
public class MadLifeService {
private final MadPlayService madPlayService;
public MadLifeService(MadPlayService madPlayService) {
this.madPlayService = madPlayService;
}
}
필드 주입과 수정자 주입은 Bean이 생성된 후에 참조를 하기 때문에 애플리케이션이 아무런 오류나 경고 없이 구동되고, 실제 코드가 호출될 때까지 문제를 알 수 없습니다.
반면, 생성자를 통해 주입하고 실행하면 BeanCurrentlyInCreationException이 발생하게 됩니다. 객체 생성 시점에 Bean을 주입하기 때문에 서로 참조하는 객체가 생성되지 않은 상태에서 그 Bean을 참조하기 때문에 오류가 발생한다.
따라서, 순환 참조가 있는 객체 설계는 잘못된 설계이기 때문에 생성자 주입을 사용하여 순환 참조되는 설계를 사전에 막아야 한다.
생성자 주입에서는 필드를 final로 선언할 수 있다는 장점이 있습니다. 이로인해 런타임에서 의존성을 주입받는 객체가 변할 일이 없어지게 됩니다.
필드 주입이나 수정자 주입에서는 불필요한 수정의 가능성을 열어두게 되고, 이는 OOP(Object-Oriented Programming)의 5가지 원칙중 OCP(Open-Closed Principal)를 위반하게 됩니다.
그러므로 생성자 주입을 사용하여 변경 가능성을 배제하고, 불변성을 보장하는 것이 좋습니다.
생성자 주입을 사용하면 테스트 코드를 조금 더 편리하게 작성할 수 있습니다.
https://dev-coco.tistory.com/70
https://madplay.github.io/post/why-constructor-injection-is-better-than-field-injection