의존성 주입의 방법에 대해서 차이점을 알아보자.
private UserService service;
private DefaualtMailServiceInterImpl registerMail;
public UserController(UserService service, DefaualtMailServiceInterImpl registerMail) {
this.service = service;
this.registerMail = registerMail;
}
현재는 생성자 방식으로 주입을 하고 있다. 하지만..
롬복 생성자 인젝션
setter autowired 인젝션
등등 무엇으로 또 할 수 있으며 각자의 차이가 무엇인지 분석하고 알고가자.
피드백 문제 해결
생성자 주입은 클래스의 생성자를 통해 의존성을 주입하는 방식입니다.
주입 받을 의존성을 final로 선언할 수 있어 불변성을 보장할 수 있습니다.
객체 생성 시점에 의존성이 모두 주입되므로, 객체의 일관성과 안정성을 보장할 수 있습니다.
테스트하기 쉽고 의존성이 명시적으로 드러나므로 코드의 가독성과 유지보수성을 높일 수 있습니다.
@Service
public class UserService {
private UserRepository userRepository;
private MemberService memberService;
public UserService(UserRepository userRepository, MemberService memberService) {
this.userRepository = userRepository;
this.memberService = memberService;
}
}
필드 주입은 의존성을 클래스의 필드에 직접 주입하는 방식입니다.
주입 받을 의존성을 public 또는 private 필드로 선언합니다.
코드의 양을 줄일 수 있고, 편리한 구현이 가능합니다.
하지만 의존성이 외부에서 직접 접근 가능하므로 캡슐화 원칙에 어긋날 수 있고, 테스트하기 어렵고 유연성이 떨어질 수 있습니다.
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private MemberService memberService;
}
세터 주입은 의존성을 객체의 세터 메서드를 통해 주입하는 방식입니다.
의존성 주입 순서가 유연하게 조정될 수 있어서 일부 의존성만 필요한 경우에 유용합니다.
선택적으로 의존성을 주입할 수 있으므로, 의존성이 필수적이지 않은 경우 유연하게 처리할 수 있습니다.
하지만 세터 메서드가 많아지면 코드의 가독성이 저하될 수 있으며, 세터 메서드를 통해 잘못된 의존성을 주입할 수 있는 위험성도 있습니다.
@Service
public class UserService {
private UserRepository userRepository;
private MemberService memberService;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Autowired
public void setMemberService(MemberService memberService) {
this.memberService = memberService;
}
}
캡슐화 원칙 위반: 필드 주입은 주입 받을 의존성을 public 또는 private 필드로 선언합니다. 이는 객체의 캡슐화 원칙을 위반하는 것입니다. 의존성이 외부에서 직접 접근 가능하므로 객체의 내부 상태를 외부에서 변경할 수 있으며, 객체의 일관성과 불변성을 유지하기 어렵게 됩니다.
유연성의 감소: 필드 주입은 의존성을 주입받을 필드를 final로 선언할 수 없으므로, 필드의 변경이 자유롭게 이루어질 수 있습니다. 이는 의존성이 변경될 경우 해당 필드를 사용하는 모든 부분을 수정해야 한다는 의미입니다. 이로 인해 유지보수성이 저하되며, 의존성 변경에 따른 리팩토링 비용이 증가합니다.
테스트의 어려움: 필드 주입은 의존성을 객체의 필드에 직접 주입하므로, 테스트할 때 의존성을 모의(mock) 객체로 대체하기 어렵습니다. 의존성을 목적에 맞게 대체하여 테스트하려면 필드에 접근할 수 있는 setter 메서드나 다른 방법을 통해 값을 변경해야 합니다.
의존성 감추기 어려움: 필드 주입은 의존성이 클래스의 필드에 직접 노출되므로, 해당 클래스가 어떤 의존성을 사용하는지를 외부에 노출시킵니다. 이는 클래스의 구현 세부 사항을 외부에 노출시키고, 의존성의 변경으로부터 자유로워지기 어렵게 만듭니다.