ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring - 다양한 의존관계 주입 방법(생성자 주입, 수정자 주입, 필드 주입)
    Spring/Spring 2022. 1. 24. 12:31
    728x90
    반응형

     

    의존관계 주입 방법

    1. 생성자 주입
    2. 수정자 주입 (setter 주입)
    3. 필드 주입
    4. 일반 메서드 주입

     

     

    생성자 주입

     

    • 생성자를 통해서 의존 관계를 주입하는 방법
    • 생성자 호출 시점에 딱 1번만 호출되는 것을 보장한다.
    • 불변, 필수 의존관계에 사용
    • 불변 : 한번 주입하면 주입된 인스턴스는 변하지 않는 것을 보장
    • 필수 : 주입받는 필드에 final 키워드를 이용함으로써 반드시 주입받아야 되는 것을 보장
    • @Autowired를 생략해도 자동 주입이 된다.

     

    @Component
    public class OrderServiceImpl implements OrderService {
    	private final MemberRepository memberRepository;
    	private final DiscountPolicy discountPolicy;
        
    	@Autowired // 생략 가능
    	public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    		this.memberRepository = memberRepository;
    		this.discountPolicy = discountPolicy;
    	}
    }

     

     위 코드를 보면 생성자를 통해 의존관계가 주입되는 것을 볼 수 있다. 생성자는 인스턴스가 생성될 때
    단 '1번'만 실행되므로 주입받은 인스턴스가 변하지 않는 '불변'을 보장받는다. 또한 만약 의존관계 주입 시 실수로 주입되지 않는 경우 (생성자에서 memberRepositorydiscountPolicy를 주입받지 못한 경우) final 키워드가 주입받는 필드에 있으므로 컴파일 오류가 일어나게 된다. 즉, final 키워드를 이용함으로써 해당 인스턴스를 반드시 주입받아야 되는 '필수'를 보장해준다.

     

     


     

    수정자 주입(setter 주입)

     

    • setter를 이용해 의존관계를 주입하는 방법
    • 선택, 변경 가능성이 있는 의존관계에 사용
    • 자바빈 프로퍼티 규약의 setter 메서드 방식을 이용한다.

     

    @Component
    public class OrderServiceImpl implements OrderService {
    	private MemberRepository memberRepository;
    	private DiscountPolicy discountPolicy;
        
    	@Autowired
    	public void setMemberRepository(MemberRepository memberRepository) {
    		this.memberRepository = memberRepository;
    	}
        
    	@Autowired
    	public void setDiscountPolicy(DiscountPolicy discountPolicy) {
    		this.discountPolicy = discountPolicy;
    	}
    }

     

     위 코드를 보면 수정자를 통해 의존관계가 주입되는 것을 볼 수 있다. 여기서 주의할 점은 클라이언트에서 setMemberRepository 메서드에 통해 인스턴스를 넘겨서 해당 빈을 컨테이너에 찾는 것이 아닌 스프링 컨테이너가 모든 빈을 생성한 이후 의존관계를 설정할 때 직접 수정자 메서드 파라미터에 명시된 타입을 가지고 컨테이너에 찾아서 주입을 해준다는 것을 명심하자.

     


     

     

    필드 주입

     

    • 필드에 직접 의존관계 주입하는 방법
    • 코드가 간결해지는 장점이 있지만 외부에서 변경이 불가능하여
      테스트 코드 작성하기가 힘들어지는 단점이 존재
    • 순수 자바 코드로 테스트 코드를 작성하기 힘들다. 즉, DI 프레임워크가 있어야 테스트 코드 작성 가능

     

    @Component
    public class OrderServiceImpl implements OrderService {
    	@Autowired
     	private MemberRepository memberRepository;
        
     	@Autowired
     	private DiscountPolicy discountPolicy;
    }

     

     테스트 코드 작성하기 힘들다는 말은 무슨 말일까? 위 코드를 보면 OrderServiceImpl은 스프링 컨테이너에 빈으로 등록이 되면서 @Autowired를 통해 자동 의존관계 주입이 이루어진다. OrderServiceImpl에 관한 테스트 코드를 작성할 때 의존 관계를 주입받는 해당 필드 MeberRepositoryDiscountPolicy들은 순수 자바 코드로 접근할 수 있는 방법이 없게 된다. 생성자 주입은 인스턴스를 생성할 때 주입할 수 있고, setter 주입은 인스턴스를 생성한 후 setter 메서드를 호출하여 주입할 수 있었지만 위 코드는 해당 필드에 접근할 수 있는 방법이 없기 때문에 테스트 코드를 작성하기 힘들다.


     

     

    일반 메서드 주입

     

    • 일반 메서드에 의존관계 주입 방법
    • 생성자 주입처럼 한 번에 여러 필드를 주입받을 수 있다.
    • 일반적으로 잘 사용하지 않는다

     

    @Component
    public class OrderServiceImpl implements OrderService {
    	private MemberRepository memberRepository;
    	private DiscountPolicy discountPolicy;
        
    	@Autowired
    	public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    	this.memberRepository = memberRepository;
    	this.discountPolicy = discountPolicy;
    	}
    }

     

     

    옵션 처리는 쓸 일이 별로 없을 것 같아 공부하면서 쓰이는 곳이 있으면 정리하려고 한다.

     

     

    728x90
    반응형

    댓글

Designed by Tistory.