다음과 같은 구성으로 간단한 회원 관리를 할 수 있는 예제를 만들어본다.
- domain: 회원을 관리할 멤버 클래스를 포함한다.
- repository: 데이터를 처리할 repository class를 포함한다.
- service: 비즈니스 로직(회원관리 로직)을 수행하는 service class를 포함한다.
- controller: 외부의 요청을 받아 로직을 수행할 controller class를 포함한다.
domain 패키지에 회원을 관리할 Member 클래스를 만든다.
package hello2.hello2spring.domain;
public class Member {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
id와 name을 가지며 이를 get, set 할 수 있는 getter와 setter를 만든다.
repository로 사용할 인터페이스를 만든다.
package hello2.hello2spring.repository;
import hello2.hello2spring.domain.Member;
import java.util.List;
import java.util.Optional;
public interface MemberRepository {
Member save(Member member);
Optional<Member> findById(Long id);
Optional<Member> findByName(String name);
List<Member> findAll();
}
데이터를 어떻게 저장할 지 방법이 정해지지 않은 경우에 인터페이스를 만들고 임시로 구현체 클래스를 만들어서 개발을 진행할 수 있다. 데이터 관리 방법이 변경되면 인터페이스를 새로 구현하여 사용할 수 있다.
인터페이스를 구현할 MemoryMemberRepository 클래스를 만든다.
package hello2.hello2spring.repository;
import hello2.hello2spring.domain.Member;
import org.springframework.stereotype.Repository;
import java.util.*;
@Repository
public class MemoryMemberRepository implements MemberRepository{
private static Map<Long,Member> store = new HashMap<>();
private static long sequence = 0L;
@Override
public Member save(Member member) {
member.setId(++sequence);
store.put(member.getId(), member);
return member;
}
@Override
public Optional<Member> findById(Long id) {
return Optional.ofNullable(store.get(id));
}
@Override
public Optional<Member> findByName(String name) {
return store.values().stream()
.filter(member -> member.getName().equals(name))
.findAny();
}
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
public void clearStore() {
store.clear();
}
}
MemoryMemberRepository는 회원저장, id로 찾기, name으로 찾기, 전체 회원 조회, 저장소 클리어의 기능을 포함한다.
@Repository 어노테이션을 사용한다.
비즈니스 로직(회원관리) 을 수행하는 MemberService 클래스를 구현한다.
package hello2.hello2spring.service;
import hello2.hello2spring.domain.Member;
import hello2.hello2spring.repository.MemberRepository;
import hello2.hello2spring.repository.MemoryMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
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) {
memberRepository.findByName(member.getName())
.ifPresent(m -> {
throw new IllegalStateException("이미 존재하는 회원입니다.");
});
}
//전체 회원 조회
public List<Member> findMembers() {
return memberRepository.findAll();
}
public Optional<Member> findOne(Long memberId) {
return memberRepository.findById(memberId);
}
}
회원가입, 전체회원조회, id로 회원조회 등의 기능을 포함한다.
Repository 는 데이터를 저장하고 조회하는 등의 직접적인 데이터 처리를 하는 간단한 기능들로 구현하고,
Service 는 Repository의 기능을 이용하여 실제 비즈니스 로직이 수행되도록 구현한다.
@Service, @Autowired 사용