이번 시간에는 스프링 빈을 등록하고 의존관계 설정을 해보았다.
화면을 붙이고 싶은데 그럴려면 컨트롤러와 뷰템플릿이 필요하다!
MemberController가 MemberService를 통해 가입하고
MemberService를 통하여 조회하여야한다 그럴때 의존관계가 필요하다
package hello.hellospring.controller;
import org.springframework.stereotype.Controller;
@Controller
public class MemberController {
}
컨트롤러 패키지 하위에 MemberController를 생성하고 @Controller애너테이션을 주면
기능은 아무렇지 않지만 어떤 일이벌어지냐면
스프링 뜰때 스프링 컨테이너라는 통이 생기는데 거기에 @Controller애너테이션이 있으면
MemberController 객체를 생성하여 스프링에 넣어두고 스프링이 관리를 한다!
package hello.hellospring.controller;
import hello.hellospring.service.MemberService;
import org.springframework.stereotype.Controller;
@Controller
public class MemberController {
private final MemberService memberService = new MemberService();
}
멤버 서비스를 가져다가 써야해서 new로 생성하여 쓸 수 도 있다 그런데!
스프링이 관리를 하게 되면 다 스프링 컨테이너에 등록을 하여 받아 쓰도록 바꿔야한다
왜냐하면 new를 쓰게되면 다른 컨트롤러에서 멤버 서비스를 가져다가 쓰게 되는데는 문제가 생긴다
그렇기에
여러개의 인스턴스를 생성할 필요가 없이 하나만 생성하고 공용으로 쓰면 된다!
스프링 컨테이너한테 등록을 하고 쓰면 하나만 등록하게 된다
package hello.hellospring.controller;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService){
this.memberService = memberService;
}
}
생성자로 연결해주고 Autowired애너태이션을 주면 된다.
생성자에 Autowired라고 되어있으면
스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다.
이렇게 객체 의존관계를 외부에서 넣어주는 것을 DI (Dependency Injection)
의존성 주입이라 한다. 하지만! 코드를 실행시키면
Parameter 0 of constructor in hello.hellospring.service.MemberService required a bean of type 'hello.hellospring.repository.MemberRepository' that could not be found.
MemberService를 찾을 수 없다고한다

MemberService는 순수한 자바클래스 이기때문에 스프링이 알 수 있는 방법이 없다!
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class MemberService {
private final MemberRepository memberRepository;
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);
}
}
메서드 위에 @Service애너테이션을 주게 되면 스프링이 올라올때 스프링 컨테이너에 memberService를 등록해준다
package hello.hellospring.repository;
import hello.hellospring.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 또한 @Repository 애너테이션을 해주어야 한다
이것이 정형화된 패턴이다.
컨트롤러 서비스 리포지토리.
컨트롤러를 통하여 외부 요청을 받고
서비스에서 비즈니스 로직을 만들고
리포지토리에서 데이터를 저장하고 하는것이 정형화된 패턴이다.
이렇게 애너테이션을 해주면 스프링이 컨트롤러 서비스 리포지토리를 가지고 올라온다!
MemberService 생성자에 Autowired 애너테이션을 주면 3개가 연결된다!
스프링 빈을 등록하는데에는 2가지 방법이있다.
여기까지 한 것이 컴포넌트 스캔과 자동 의존관계 설정 방식이다.
스프링이 올라올때 컴포넌트와 관련된 애너테이션이 있으면 걔들은 객체를 하나씩 생성하여
스프링 컨테이너에 등록을 한다 Autowired는 연관관계를 연결해주고 그래서 MemberController가
MemberService를 쓸 수 있게해주고 MemberService가 MemberRepository를 쓸 수 있게 해주게
된다!
참고로 스프링은 스프링 컨테이너에 스프링 빈을 등록할때, 기본으로 싱글톤으로 등록한다.(유일하게 하나만
등록하여 공유한다.) 따라서 같은 스프링 빈이면 모두 같은 인스턴스이다. 서렂ㅇ으로 싱글톤이 아니게 할 수는
있지만 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.
자바 코드로 직접 스프링 빈 등록하는 방법도 있다.
'웹프로그래밍 > Spring 입문' 카테고리의 다른 글
| 12. 회원 웹기능 - 홈 화면 추가 (0) | 2021.06.23 |
|---|---|
| 11. 자바 코드로 직접 스프링 빈 등록하기 (0) | 2021.06.22 |
| 9. 회원 서비스 테스트 (0) | 2021.06.21 |
| 8. 회원 서비스 개발 (0) | 2021.06.19 |
| 7. 회원 리포지토리 테스트 케이스 작성 (0) | 2021.06.19 |