스프링은 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능과 자동으로 의존성을 주입할 수 있는 기능도 제공한다. 다음 실습을 통해 자세히 알아보자
package hello.hellospring.controller;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
@Controller
애노테이션을 붙이면 스프링 컨테이너에서 MemberController
객체를 생성해서 관리해준다 → 스프링 빈으로 자동 등록
생성자에 @Autowired
애노테이션이 있으면 스프링이 연관된 객체를 스프링 컨테이너에 찾아 넣어준다 → 의존성 주입(DI)
MemberService
와 MemoryMemberRepository
에 각각 @Service
와 @Repository
애노테이션을 붙여주지 않으면 스프링 빈으로 등록이 되지 않기 때문에 의존관계를 설정할 수 없어 다음과 같은 오류가 발생한다
MemberService
와 MemoryMemberRepository
에 각각 @Service
와 @Repository
애노테이션을 붙여준다
MemberService
package hello.hellospring.service;
import hello.hellospring.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
...
}
MemoryMemberRepository
package hello.hellospring.repository;
import org.springframework.stereotype.Repository;
@Repository
public class MemoryMemberRepository implements MemberRepository {
...
}
@Component
애노테이션이 있으면 스프링 빈으로 자동 등록된다@Component
를 포함하는 다음 애노테이션도 스프링 빈으로 자동 등록된다@Container
@Service
@Repository
@Container
, @Service
, @Repository
→ 스프링 빈 등록@Autowired
→ 자동 의존관계 설정(의존성 주입)참고
- 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록
- 같은 스프링 빈이면 모두 같은 인스턴스
@Autowired
를 통한 DI는helloController
,memberService
등과 같이 스프링이 관리하는 객체에서만 동작한다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.
설정 파일에서 스프링 빈을 직접 등록할 수 있다 → @Configuration
, @Bean
애노테이션 사용
XML로 설정하는 방식도 있지만 최근에는 잘 사용하지 않는다
위의 예제에서 회원 서비스와 회원 리포지토리의 @Service
, @Repository
, @Autowired
애노테이션을 제거하고 진행한다
src/main/java/hello.helloSpring
하위에 SpringConfig.java
파일을 생성 후 다음과 같이 작성한다
package hello.hellospring;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
참고
- 실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용한다
- ⭐ 정형화되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다
DI에는 생성자 주입, 필드 주입, setter 주입 3가지 방법이 있다
의존관계가 실행중에 동적으로 변하는 경우는 거의 없으므로 생성자 주입을 권장한다
생성자를 통해 의존 관계를 주입하는 방법
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService
}
필드에 바로 의존 관계를 주입하는 방법
@Autowired
private MemberService memberService;
setter 메서드에 의존 관계를 주입하는 방법
private final MemberService memberService;
@Autowired
public setMemberService(MemberService memberService) {
this.memberService = memberService
}
출처 - 인프런 '스프링 입문' 강의