컴퍼넌트 스캔과 자동 의존관계 설정
멤버컨트롤러가 멤버 서비스를 통해서 회원가입하고 데이터를 조회할 수 있어야함
=>의존관계 (멤버컨트롤러가 멤버서비스를 의존한다)
@Controller
public class MemberController {
}
스프링컨테이너가 컨트롤러 애노테이션이 있으면 객체를 생성해서 스프링에 넣고 관리함
그래서 컨트롤러 기능이 동작할 수 있다
@Controller
public class MemberController {
private final MemberService memberService = new MemberService();
}
private final MemberService memberService = new MemberService();
이 코드의 문제:다른 컨트롤러가 멤버서비스를 가져다 쓸 수 있을텐데 멤버서비스는 join 기능만 있음
별 기능도 없는데 여러개 생성할 이유가 없다 하나만 생성해서 공용으로 쓰면 좋다
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
해결 방법:스프링 컨테이너에 하나만 등록하기
멤버컨트롤러가 생성자를 호출하는데 @Autowired가 되어있으면 멤버서비스를 스프링이 컨테이너에
있는 멤버서비스를 연결시켜준다

이렇게 하면 'hello.hellospring.service.MemberService' that could not be found. 에러남
지금 하고 있는 작업이 @Autowired 로 컨트롤러와 멤버서비스를 연결하는 작업인데 되고 있지 않다

해결방법:Service 파일과 Repository에 각각 @Service / @Repository 애노테이션을 붙이면 스프링이 스프링컨테이너에 멤버서비스를 등록해준다.
생성자에 @Autowired가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다. 이렇게
객체 의존관계를 외부에서 넣어주는 것을 DI (Dependency Injection), 의존성 주입이라 한다
지금까지 한게 컴포넌트 스캔이다
@Component
public @interface Controller {
}
어노테이션 들어가면 이런식으로 컴포넌트가 위에 달려있다
컴포넌트가 있으면 스프링이 객체를 생성해서 컨테이너에 등록함
@Autowired 는 연관관계를 연결해준다. 스프링 컨테이너에 올라가는 것들만 @Autowired 가 동작한다
컴포넌트 스캔은 hello.hellospring 패키지를 포함한 하위는 커버 가능한데 다른 곳은 스프링이 스캔 못함
헬로컨트롤러 딱 하나 멤버서비스 딱하나 이런식으로 하나만 등록된다.
자바 코드로 직접 스프링 빈 등록하기
SpringConfig
@Configuration
public class SpringConfig {
@Bean //스프링빈 등록할거야
public MemberService memberService(){
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository(){
return new MemoryMemberRepository(); //인터페이스는 new 안됨
}
}
이런식으로 직접 스프링빈을 등록할 수 있다.
실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용하고
상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다.

비즈니스 요구사항을 정리했을때 아직 데이터 저장소가 선정되지 않아서, 우선 인터페이스로 구현 클래스를 변경할 수 있도록 설계했다.
스프링빈으로 등록하면 나중에 데이터 저장소가 정해지면 MemoryMemberRepository만 교체하면 된다.
코드 수정이 없기 때문에 간편함
DI에는 필드 주입, setter 주입, 생성자 주입 이렇게 3가지 방법이 있다
필드 주입
@Controller
public class MemberController {
@Autowired private MemberService memberService;
}
필드 주입은 중간에 내가 바꿔치기할 수 없다
setter 주입
@Controller
public class MemberController {
private MemberService memberService;
@Autowired
public void setMemberService(MemberService memberService) {
this.memberService = memberService;
}
}
누군가가 멤버 컨트롤러를 사용할 때 setMemberService가 public 으로 열려있어야한다. 한번 설정되면 중간에 바꿔치기 할 일이 없는데도 public으로 계속 노출되는 현상이 발생
생성자 주입
@Controller
public class MemberController {
private final MemberService memberService;
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
애플리케이션을 조립할때 바꿔치기 하는거지 실행되면 바꿀 일이 없기 때문에 생성자 주입이 가장 좋은 방법이다.
생성자 주입 방식을 쓰면 애플리케이션 조립될 때 생성자 주입 한 번 되고 끝난다. 이후 변경 못하도록 막을 수 있기 때문에 좋다.
'Springboot' 카테고리의 다른 글
| 김영한 스프링 입문 섹션 6.스프링 DB 접근 기술 정리 (0) | 2024.03.09 |
|---|---|
| 김영한 스프링 입문 섹션 5.회원 관리 예제-웹 MVC 개발 정리 (0) | 2024.03.08 |
| 김영한 스프링 입문 섹션 3. 회원 관리 예제 실습 정리 (0) | 2024.03.07 |
| 김영한 스프링 입문:섹션2 스프링 웹 개발 기초 정리 (1) | 2024.03.05 |
| String 을 LocalDate 바꾸는 법 (0) | 2024.01.20 |