스프링 빈 이란?
@Controller
어노테이션이 달리면 스프링이 스프링 컨테이너에 컨트롤러 객체를 만들어 관리함
- 이것을 스프링 빈을 관리한다고 함
- 스프링이 인식하기 위해
@Controller
@Service
@Repository
와 같은 어노테이션을 달아 주는 것임
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired //스프링 컨테이너에서 MemberService를 의존성 주입해줌
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
- 서비스, 컨트롤러, 리포지토리를 모두 어노테이션을 활용해 스프링이 빈으로 인식할 수 있도록 함
- 생성자에
@Autowired
어노테이션을 달아서 DI를 통해 알아서 객체를 외부에서 주입해주도록 함
스프링 빈 등록방법
- 두가지 스프링 빈 등록방법이 있음. 모두 알아야 함
컴포넌트 스캔과 자동 의존관계 설정
- 위에서 어노테이션을 사용한 방식이 컴포넌트 스캔
@Component
어노테이션이 있으면 스프링 빈으로 자동 등록
- 서비스, 컨트롤러, 리포지토리 어노테이션이
@Component
어노테이션을 포함해서 이 어노테이션들을 달면 스프링 빈으로 자동 등록됨
- 스프링 빈 등록이 가능한 범위는
HelloSpringApplication
이 있는 패키지와 그 하위 패키지들에서 가능함
자바 코드로 직접 스프린 빈 등록하기
- MemberService의
@Service
@Autowired
, MemoryMemberRepository의 @Repository
어노테이션을 지워준다
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService(){
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository(){
return new MemoryMemberRepository();
}
}
@Configuration
어노테이션
@Bean
어노테이션으로 리턴하는 객체를 스프링 컨테이너에 빈으로 등록하게 함
- 스프링은 컨테이너에 컴포넌트를 등록할 때 기본으로 싱글톤으로 등록함(유일하게 하나만 등록해서 공유함)
- 설정으로 싱글톤이 아니게 할 수 있지만 특별한 경우를 제외하면 거의 싱글톤 사용
DI
- DI에는 필드 주입, setter 주입, 생성자 주입 이렇게 3가지 방법이 있음
- 생성자 주입
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired //스프링 컨테이너에서 MemberService를 의존성 주입해줌
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
- 지금까지 사용한 방식
- 생성자를 통해 주입함
- 요즘 권장하는 스타일
- 필드 주입
@Controller
public class MemberController {
@Autowired
private MemberService memberService;
// @Autowired //스프링 컨테이너에서 MemberService를 의존성 주입해줌
// public MemberController(MemberService memberService) {
// this.memberService = memberService;
// }
}
- 생성자 없이 필드에
@Autowired
를 달아줄 수 있음
- 필드 주입은 뭔가 바꿀 수 있는 방법이 없음 (별로 안좋음)
- Setter 주입
@Controller
public class MemberController {
private MemberService memberService;
@Autowired
public void setMemberService(MemberService memberService) {
this.memberService = memberService;
}
// @Autowired //스프링 컨테이너에서 MemberService를 의존성 주입해줌
// public MemberController(MemberService memberService) {
// this.memberService = memberService;
// }
}
- Setter에
@Autowired
를 달아줌
- 생성은 생성대로 되고 나중에 setter를 통해 주입됨
- 단점 : Setter가 public 이어야 함 (외부에 노출이 됨)
결론
- 생성자 주입 써라
- 정형화된 컨트롤러, 리포지토리, 서비스는 컴포넌트 스캔 방식, 정형화되지 않거나 상황에 따라 구현 클래스를 변경해야 하는 경우 설정을 통해 스프링 빈으로 등록함
즉 인터페이스의 구현체만 바꿔 끼워야 할 경우 유용함
그냥 @Bean
이 달린 메소드의 리턴 객체만 바꿔주면 됨
@Autowired
는 스프링 빈으로 등록된 객체에 대해서만 동작함