//package, import 생략
@Service
@Transactional
public class MemberService {
@Autowired
private MemberRepository memberRepository;
//이하 생략
}
@Autowire로 spring이 spring bean에 등록되어 있는 MemberRepository를 인젝션해준다.
테스트할 때 MemberRepository를 못 바꿈(필드도 private으로 되어있고..)
setter Injection 사용하기
@Service
@Transactional
public class MemberService {
private MemberRepository memberRepository;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
...
}
테스트 코드 작성 시 직접 메서드를 통해 주입 가능하다
가짜 MemberRepository같은 주입이 가능
런타임 시점에 누군가 코드를 바꿀 수 있다
보통 애플리케이션 로딩 시점에 세팅 조립이 다 끝난다. 그러니 중간에 누가 바꿀 일이 없음. 바뀔 수 있다는 것은 좋지 않다.
Constructor Injection(생성자 인젝션) 사용하기
@Service
@Transactional
public class MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
...
}
한 번 생성 시 완성되어버림. 중간에 set...() 해서 바꿀 수 없다
변경할 일이 없기 때문에 MemberRepository 필드는 final로 작성 권장
예를 들어, 테스트 케이스 작성 시 MemberService를 작성하는데
public stativ void main(String[] args) {
MemberService memberService = new MemberService();
}
new MemberService()에서 컴파일 에러가 남. 직접 주입해줘야 한다.
@Service
@Transactional
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
...
}
스프링에서는 생성자가 1개인 경우, @Autowired가 없어도 자동으로 인젝션해줌
여기서 Lombok을 적용시키자.
@AllArgsConstructor 얘는
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
이걸 직접 만들어준다.
이것보다 더 좋은 건 RequiredArgsConstructor가 있다.
final에 있는 필드만 가지고 생성자를 만들어준다.
@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
처음과 비교해보면
//package, import 생략
@Service
@Transactional
public class MemberService {
@Autowired
private MemberRepository memberRepository;
//이하 생략
}
@Autowired 생략 가능final 작성@RequiredArgsConstructor 어노테이션 추가, 자동으로 final 필드를 생성자로 만들어줌 MemberRepository 클래스도 이렇게 적용이 가능하다.
기존 코드
@Repository
public class MemberRepository {
@PersistenceContext
private EntityManager em;
//이하 생략
}
우선 생성자 주입을 해본다.
@Repository
public class MemberRepository {
@Autowired
private EntityManager em;
public MemberRepository(EntityManager em) {
this.em = em;
}
//이하 생략
}
@Autowired는 지울 수 있다. Spring Data JPA가 @Autowired를 지원해준다. @RequiredArgsConstructor 를 추가해준다.final로 작성해준다. 변경 코드
@Repository
@RequiredArgsConstructor
public class MemberRepository {
private final EntityManager em;
//이하 생략
}
참고로 EntityManager는 @Autowired로는 안 되고, @PersistenceContext 표준 어노테이션이 있어야 인젝션이 가능하다.
그러나 Spring Data JPA부터 @Autowired도 인젝션이 가능하도록 지원해준다.
추후에는 Spring 기본 라이브러리에서도 @Autowired도 인젝션이 가능하도록 지원할 예정이라고 한다.