private final MemberService memberService = new MemberService();
의 문제점은 다른 컨트롤러에서 가져다가 쓸 때 여러개를 생성해서 쓰는게 아니라 하나를 생성해서 공용으로 사용하면 된다.
스프링 컨테이너에 등록해서 사용하면 된다!!!!
private final MemberService memberService;
@Autowired // Autowired는 memberService를 스프링이 스프링컨테이너에 연결시켜준다.
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
이런식으로 하면 해결 된다.
Consider defining a bean of type 'hello.hellospring.service.MemberService' in
your configuration.
MemberService가 컨테이너에 등록되어 있지 않아서 발생하는 오류이다.
순수한 자바 클래스이다. 스프링이 알 수 있는 방법이 없다.
스프링 빈에 등록되어 있는 MemberService 객체를 가져다가 넣어주는 것. 의존관계를 주입해 주는 것
컴포넌트 스캔과 자동 의존관계 설정
스프링이 올라올 때 관련된 @Component 어노테이션이 있으면 다 객체로 생성해서 컨테이너에 스프링 빈으로 자동 등록 한다. Autowired는 연관관계를 연결해준다.
컴포넌트 대상은 @SpringBootApplication 같은 패키지나 하위 패키지 안에서만 가능하다.
스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다(유일하게 하나만 등록해서 공유한다) 따라서 같은 스프링 빈이면 모두 같은 인스턴스다.
자바 코드로 직접 스프링 빈 등록하기
DI에는 필드 주입, setter 주입, 생성자 주입 이렇게 3가지 방법이 있다.
생성자 주입을 사용한다. 스프링컨테이너가 올라갈 가면서 세팅될 때 생성자가 한번 들어오고 끝난다. 생성 시점에 넣고 그다음 변경 없게 만든다. setter 주입은 public으로 열려있는게 문제이고(호출 되지 말아야할 메서드), 필드 주입은 변경이 힘들다.
직접 설정파일을 운영할 때 장점, 변경이 매우 쉽다.
@Autowired는 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다. 스프링 컨테이너 올라간 것들만 동작한다.