본문 바로가기

back-end/spring

spring/ 의존 관계 자동 주입 - 생성자 주입을 사용하자

 

생성자 주입

생성자를 통해서 의존 관계를 주입한다.

 

  • 생성자가 호출되는 시점에 단 한번만 호출되는 것을 보장한다
  • 불변, 필수 의존 관계에 사용한다.
  • 생성자가 하나만 존재한다면 @Autowired를 생략해도 자동으로 의존 관계가 주입된다.

e.g.

 

@Component
public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final PointPolicy pointPolicy;
	
    @Autowired //생성자가 1개만 존재하므로 @Autowired를 생략할 수 있다
    public OrderServiceImpl(MemberRepository memberRepository, PointPolicy pointPolicy) {
        this.memberRepository = memberRepository;
        this.pointPolicy = pointPolicy;
    }

    ...
}

 

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

1. 불변

대부분의 의존 관계는 한번 주입되면 애플리케이션 종료 시점까지 변경되지 않아야 한다. 수정자 주입의 경우 setter 메서드가 public으로 접근이 열려 있기 때문에 변경에 취약하다. 

2. 누락 방지

생성자 주입을 사용하는 경우 주입되어야 하는 데이터가 누락되었을 때 컴파일 오류가 발생하므로 누락을 방지할 수 있다.

3. final

생성자 주입을 사용할 때 필드는 final로 지정될 수 있다. 필드를 final로 지정하는 경우 값이 필수로 할당되어야 한다. 따라서, 컴파일 시점에 값 설정이 누락되는 경우를 방지할 수 있다. 

 


수정자(setter) 주입

setter 메서드를 사용해 의존 관계를 주입한다.

  • 선택, 변경 가능성이 있는 의존 관계에 사용한다

 

e.g.

@Component
public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final PointPolicy pointPolicy;
	
    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
    	this.memberRepository = memberRepository;
    }
    
    @Autowired
    public void setPointPolicy(PointPolicy pointPolicy) {
    	this.pointPolicy = pointPolicy;
    }

    ...
}

 


필드 주입

필드에 바로 의존 관계를 주입한다

  • 외부에서 변경이 불가능해 테스트가 힘들다
  • 테스트 코드나 스프링 설정을 위한 @Configuration을 제외하고는 사용이 권장되지 않는다.

 


일반 메서드 주입

일반 메서드를 통해 의존 관계를 주입한다.

  • 한번에 여러 필드를 주입 받는 것이 가능하다
  • 일반적으로 잘 사용되지 않는다

 

e.g.

public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final PointPolicy pointPolicy;
	
    @Autowired
    public void init(MemberRepository memberRepository, PointPolicy pointPolicy) {
        this.memberRepository = memberRepository;
        this.pointPolicy = pointPolicy;
    }
}

 


자동 주입 대상을 옵션으로 처리하기

주입할 스프링 빈이 없는 경우, 동작을 위해 @Autowired의 옵션을 설정해주어야 한다.

 

@Autowired(required =false)

자동 주입할 대상이 없는 경우 수정자 메서드 자체를 호출하지 않는다.

@Autowired(required = false)
public void setNoBean1(Member member) {...}

 

@Nullable

자동 주입할 대상이 없는 경우 null이 입력된다.

@Autowired
public void setNoBean2(@Nullable Member member) {...}

 

Optional<>

자동 주입할 대상이 없는 경우 Optional.empty가 입력된다.

@Autowired(required=false)
public void setNoBean3(Optional<Member> member) {...}