컴포넌트 스캔과 자동 의존관계 설정
MemberController 가 MemberService 와 MemberRepository 를 사용할 수 있게 의존관계를 준비하자
[현재 package 구성]
회원 컨트롤러에 의존관계 추가
•
생성자에 @Autowired 가 있으면 스프링이 연관된 객체를 스프링 컨테이너에 찾아서 넣어준다.
•
의존성 주입(Dependency Injection)
객체 의존관계를 외부에서 넣어주는 것이다. @Autowired 에 의해 스프링이 주입한다.
여기까지만 하면 다음과 같은 오류가 발생한다.
Consider defining a bean of type ‘example.memberManagement.service.MemberService’ in your configuration.
Java
복사
이말은 아직 memberService 가 스프링 빈으로 등록되어 있지 않다는 뜻이다.
[현재 상태]
컴포넌트 스캔 원리
•
@Component 가 있으면 스프링 빈으로 자동 등록된다.
•
@Controller 가 자동 등록된 이유도 컴포넌트 스캔 때문이다.
•
@Component 를 포함하는 다음 Annotation 도 스프링 빈으로 자동 등록된다.
◦
@Service
◦
@Repository
회원 서비스 스프링 빈 등록
참고
생성자에 @Autowired 를 사용하면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입한다. 생성자가 1 개만 있으면 @Autowired 는 생략할 수 있다.
회원 리포지토리 스프링 빈 등록
여기까지 하면 스프링 컨테이너가 다음과 같이 구성된다.
즉, memberService 와 memberRepository 가 스프링 컨테이너에 빈으로 등록되었다는 것이다.
참고
스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다.(유일하게 하나만 등록해서 공유한다) 따라서 같은 스프링 빈이면 모두 같은 인스턴스다. 설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.
에러
강사님과 똑같이 실행했는데도 자꾸 다음과 같은 오류가 발생했었다.
Annotation 도 멀쩡했고, 코드도 틀린부분이 없어서 왜 그럴까 약 한시간정도 정보 찾아보고 난리났는데, 나한테 해당하는 부분이 없었따,,
겨우 찾아낸 오류는 정말 어이없게도 package 위치를 잘못 설정한것에서 기인한 것이였다. 정신차려 김시니,,
어이,, service package 쿤,, 왜 거기있는 거냐고,,
자바 코드로 직접 스프링 빈 등록하기
Service 패키지에 SpringConfig 클래스를 생성한다.
그리고 Annotation 을 통해 의존관계를 맺어주면 된다.
위와 같은 그림이 목표이므로, 코드는 아래와 같이 작성하면 된다.
향후 메모리 리포지토리를 다른 리포지토리로 변경 할 예정이라면, 첫번째로 했던 방식인 컴포넌트 스캔 방식 대신에 이 방식을 사용해야 한다.
참고
•
XML 로 설정하는 방식도 있지만 최근에는 잘 사용하지 않으므로 생략한다.
•
DI 에는 필드 주입, setter 주입, 생성자 주입 이렇게 3가지 방법이 있다. 의존관계가 실행중에 동적으로 변하는 경우는 거의 없으므로 생성자 주입을 권장한다.
◦
필드 주입
필드에서 바로 @Autowired 를 통해 의존성을 주입하는 방식이다. 사용법이 매우 간단하다는 장점이 있지만 주입된 객체를 immutable 한 상태를 만들수 없다는 단점이 존재한다. 즉, Spring DI 컨테이너 밖에서는 작동할 수 없는 코드가 된다.
◦
setter 주입
주입 받는 객체가 변경될 가능성이 있는 경우에 사용하는 방식이다. 하지만 실제 개발에서는 의존 관계 주입의 변경이 필요한 상황이 거의 없다.
◦
생성자 주입
생성자 주입 방식을 사용하게 되면 객체의 불변성을 확보할 수 있기 때문에 주입받을 필드를 final 로 선언이 가능하다. 또한 컴파일 시점에 누락된 의존성을 확인할 수 있다.
•
실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용한다. 그리고 정형화 되어있지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다.
@Autowired 를 통한 DI 는 스프링이 관리하는 객체에서만 동작한다.
스프링 빈으로 등록하지 앟고 내가 직접 생성한 객체에서는 동작하지 않는다.