본 포스팅은 인프런 - 스프링 입문을 강의를 바탕으로 공부하고 정리한 글입니다.
스프링 빈을 등록하는 2가지 방법에 대해 알아보자.
- 컴포넌트 스캔과 자동 의존관계 설정
- 자바 코드로 직접 스프링 빈 등록하기
컴포넌트 스캔과 자동 의존관계 설정
앞서 회원 도메인 객체, 회원 서비스, 회원 리포지토리를 만들어주었다.
이를 화면에 보여주기 위해 회원 컨트롤러와 뷰 템플릿이 필요하다.
때문에 회원 컨트롤러를 만들어 줘야 하는데, 이때 회원 컨트롤러가 회원 서비스를 통해 회원 가입 및 조회를 할 수 있어야 한다.
이를 위해 회원 컨트롤러가 회원 서비스 및 회원 리포지토리를 사용할 수 있도록 의존관계를 준비해줘야 한다.
📁 controller/MemberController
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
- @Controller
- 컨트롤러에 사용하는 애노테이션이다.
- 해당 클래스(MemberController)로 객체를 생성해 스프링 컨테이너에 스프링 빈으로 등록한다.
- @Autowired
- 생성자에 @Autowired를 사용하면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈(memberService)을 찾아서 넣어준다.
- 이렇게 객체 의존관계를 외부에서 넣어주는 것을 DI(Dependency Injection), 즉 의존성 주입이라 한다.
💡 DI(Dependency Injection) 구현 방법
1. 생성자 주입 → 의존관계가 실행 중에 변하는 경우는 거의 없으므로 생성자 주입을 권장한다.
2. 필드 주입
3. setter 주입
컨트롤러를 만들어 주고 애플리케이션을 실행시키니 다음과 같은 오류가 발생한다.
오류 메세지를 확인하니 MemberController 객체 생성시 주입해줄 MemberService 스프링 빈을 찾을 수 없어서 오류가 발생한 것이다.
해결을 위해 MemberService와 MemoryMemberRepository도 스프링 컨테이너에 스프링 빈으로 등록해주자.
📁 service/MemberService
@Service
public class MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
- @Service
- 서비스에 사용하는 애노테이션
- 해당 클래스의 객체를 생성해 스프링 컨테이너에 스프링 빈으로 등록한다.
- @Autowired
- 생성자에 @Autowired를 사용하면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈(memberRepository)을 찾아서 넣어준다. → DI(의존성 주입)
📁 repository/MemoryMemberRepository
@Repository
public class MemoryMemberRepository implements MemberRepository {
...
}
- @Repository
- 리포지토리에 사용하는 애노테이션
- 해당 클래스의 객체를 생성해 스프링 컨테이너에 스프링 빈으로 등록한다.
컴포넌트 스캔의 원리
지금까지 @Controller, @Service, @Repository 애노테이션을 붙혀주는 것만으로 스프링 빈 등록이 끝났다. 어떻게 가능한 걸까?
스프링은 @Component와 관련된 애노테이션이 있으면 객체를 생성해 스프링 컨테이너에 스프링 빈으로 등록하게 된다.
사실 @Controller, @Service, @Repository 애노테이션을 살펴보면 내부적으로 @Component 포함하고 있다.
따라서 다음과 같은 애노테이션이 있으면 스프링 빈으로 자동 등록한다.
- @Component
- @Controller
- @Service
- @Repository
스프링 빈 등록 이미지
- 컴포넌트 스캔을 통해 memberController와 memberService, memberRepository가 스프링 컨테이너에 스프링 빈으로 등록되었다.
- @Autowired를 통해 각 스프링 빈의 연관관계를 연결해주기 때문에 memberController가 memberService를, memberService가 memberRepository를 쓸 수 있게 된다.
- 스프링은 스프링 컨테이너에 스프링 빈을 등록할때, 기본으로 싱글톤으로 등록한다. (유일하게 하나만 등록해서 공유)
따라서 같은 스프링 빈이면 모두 같은 객체이다. 설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.
자바 코드로 직접 스프링 빈 등록하기
스프링 빈 등록을 위한 별도의 파일을 만들어 자바 코드로 직접 등록해줄 수 있다.
앞서 진행 한 회원 서비스와 회원 리포지토리의 @Service, @Repository, @Autowired 애노테이션을 제거하고 진행하도록 한다.
📁 SpringConfig
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
- @Configuration, @Bean : 스프링은 @Configuration이 있으면 스프링 빈으로 등록하고, @Bean이 달린 로직을 호출해 스프링 빈에 등록해준다.
정리
- 실무에서는 주로 정형화 된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔 방식을 사용한다.
- 정형화 되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 직접 등록한다.
'🌱 Spring > Core' 카테고리의 다른 글
[기본] #2 회원, 주문, 할인 도메인 개발 및 테스트 (0) | 2022.02.21 |
---|---|
[기본] #1 객체 지향 설계와 스프링 (0) | 2022.02.18 |
[입문] #7 AOP (0) | 2022.02.17 |
[입문] #6 DB 접근기술(JDBC, JdbcTemplate, JPA, SpringJPA) (0) | 2022.02.16 |
[입문] #5 웹 MVC 개발 (0) | 2022.02.15 |
[입문] #3 회원관리 예제 만들기 (0) | 2022.02.15 |
[입문] #2 정적웹, MVC, API (0) | 2022.02.14 |
[입문] #1 스프링 프로젝트 환경설정 (0) | 2022.02.14 |