좋은 설계란 제약이 있는 설계이다.
많은 getter, setter는 개발자를 혼란스럽게 할 뿐이다.
스프링 컨테이너 사이클
1. 스프링 빈 모두 등록 (@Component, @Bean)
2. 빈의 연관관계를 자동으로 주입 (@Autowired)
public class MemberServiceImpl implements MemberService{
private final MemberRepository memberRepository;
// @Autowired
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
...
}
불변이고 필수적인 의존관계에서 사용
생성될 때 의존관계가 맺어지고 그 후로 변경할 필요가 없는 경우
(빈의 생성자가 하나일 경우 @Autowired
를 생략할 수 있다.)
스프링 컨테이너 사이클의 1번 과정에서 빈에 등록됨과 동시에 연관관계를 주입
나머지 주입 방식은 모두 생성자 이후에 호출이 되므로, 필드에 final 키워드를 사용할 수 없다.
public class MemberServiceImpl implements MemberService{
private MemberRepository memberRepository;
@Autowired
public void setMemberRepository(MemberRepository repository){
this.memberRepository = repository;
}
...
}
선택적이고 변경되는 의존관계에서 사용
public class MemberServiceImpl implements MemberService{
@Autowired
private MemberRepository memberRepository;
...
}
가장 간단하고 코드가 간결하지만 외부에서 주입이 불가능하다는 치명적인 단점이 있기 때문에 안티패턴이다.
테스트를 위해 더미 DB를 연결을 위해 수정하고 싶지만 필드에 박아버리면 불가능하다.
또한 스프링의 DI에 의존하기 때문에 순수한 단위테스트가 불가능한다.
(스프링부트 테스트 내 테스트 코드에서만 편의를 위해 사용)
public class MemberServiceImpl implements MemberService{
private MemberRepository memberRepository;
@Autowired
public void init(MemberRepository repository){
this.memberRepository = repository;
}
...
}
한번에 여러 필드를 주입 받을 수 있지만 수정자 주입에서 해결할 수 있기 때문에 잘 사용하진 않는다.