생각정리/Spring

스프링 의존성 주입

생각중임 2024. 3. 13. 17:49

스프링 빈을 등록하는 2가지 방법

💡 컴포넌트 스캔의 범위는 SpringBootApplication이 있는 패키지의 하위 패키지안에서만 기본적으로 유효하고 이상으로는 별도의 설정이 필요하다.
  • 컴포넌트 스캔과 자동 의존관계 설정
    • controller, service, repository 등 conponent 어노테이션을 가지고 있는 어노테이션을 사용한 등록
    • Autowired를 이용해 자동 의존관계 설정 (스프링 빈에 등록되지 않으면 사용할 수 없다.)
    • 기본적으로 싱글톤 패턴으로 등록된다. (특수한 경우 별로 설정으로 싱글톤이 아니게 설정가능)
@Repository
public class MemoryMemberRepository implements MemberRepository {

}
  • 자바 코드로 직접 스프링 빈 등록
    • Service와 Repository는 Config클래스를 만들어 @Bean 어노테이션을 사용해 직접 등록이 가능하다. 하지만, Controller는 스프링이 직접 관리를 하기 때문에 컴포넌트 스캔 방식을 이용해야 한다.
    • 기존 코드를 전혀 손대지 않고, 설정만으로 구현 클래스를 변경할 수 있다.
@Configuration
public class SpringConfig {

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}
💡 정형화된 Controller, Service, Repository 같은 코드는 컴포넌트 스캔을 사용한다. 그리고 정형화 되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다.

의존성 주입 방법

생성자 주입

@Service
public class MemberService {

    private final MemberRepository memberRepository;

    @Autowired
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
}
  • 의존관계가 실핼중에 동적으로 변하는 경우는 거의 없으므로 생성자 주입을 권장한다.
  • 생성자의 호출 시점에 1회 호출 되는 것이 보장된다.
  • 생성자가 하나만 존재할 경우 @Autowired를 생략할 수 있다.

필드 주입

@Service
public class MemberService {

		@Autowired
    private final MemberRepository memberRepository;

}
  • 외부에서 접근이 불가능하다.
  • 필드의 객체를 수정할 수 없어 권장하지 않는다.
  • 실제 코드와 무관한 테스트 코드나 설정을 위해 불가피한 경우에만 이용한다.

Setter 주입

@Service
public class MemberService {

    private final MemberRepository memberRepository;

    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
}
  • 사용하는 객체를 public으로 사용해야 하는 단점이 있다.
  • 가동중에 변경이 될 경우 문제가 발생한다.

생성자 주입을 사용해야 하는 이유

  1. 생성자 호출 이후 객체의 불변성을 보장한다.
  2. 테스트 코드의 작성이 편리하다.