등록 할 때

@Service
@Transactional
public class MemberService {

	private final MemberRepository memberRepository;

	@Autowired
	public MemberService(MemberRepository memberRepository) {
		this.memberRepository = memberRepository;
	}

	public Long join(Member member) {
		validateDuplicateMember(member);
		memberRepository.save(member);

		return member.getId();
	}

	private void validateDuplicateMember(Member member) {
		List<Member> findMembers = memberRepository.findByName(member.getName());
		if (!findMembers.isEmpty()) {
			throw new IllegalStateException("이미 존재하는 회원입니다.");
		}
	}

	@Transactional(readOnly = true)
	public List<Member> findMembers() {
		return memberRepository.findAll();
	}

	@Transactional(readOnly = true)
	public Member findOne(Long memberId) {
		return memberRepository.findOne(memberId);
	}
}

name 중복 체크가 이렇게만 하면 위험하다. 혹시라도 동 타이밍에 입력이 들어올 수 있기 때문에 DB에서 unique제약 조건을 걸어서 최후의 방어 수단으로 DB 레벨에서 걸러 낼 수 있도록 하자.

기본 생성자 주입을 사용하는 이유 (생성자 인젝션)

테스트 코드 등에서 외부에서 repository를 주입할 수가 있다. setter를 만드는 것도 가능한데 단점은 실수로 누군가가 setter를 통해서 실수로 repository를 변경할 수 있다.

최신 스프링은 생성자가 하나만 있는 경우 생성자에 @Autowired를 생략해도 된다. final 어노테이션도 넣는 것이 좋다.

그리고 이것을 쉽게 하려면! 롬복의 @AllArgsConstructor

그리고 또 이것보다 한번 더 좋은 건 @RequiredArgsConstructor 이다. 예는 final 필드만 가지고 생성자를 만든다!!

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
public class MemberService {

	private final MemberRepository memberRepository;

	// ...