의존관계 주입 방법 4가지 

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

 

 

1. 생성자 주입

  • 이름 그대로 생성자를 통해 의존관계를 주입 받는 방법
  • 특징
    • 생성자 호출시점에서 딱 한번만 호출되는 것을 보장한다.
  • 장점
    • 불변 : 두 번이상 호출이 안되기때문에 변하지 않음
    • 필수 : 생성자를 통해 들어온 값이 무조건 있어야 함
  • 생성자가 하나일때는 자동으로 @Autowired가 적용이 된다. (생략가능) 
  • 예시
@Component
public class OrderServiceImpl implements OrderService{
	
	private final MemberRepository memberRepository; 
	
	private final DiscountPolicy discountPolicy; 
	
	//생성자 (생성자가 하나라서 @Autowired 생략가능)
	@Autowired
	public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
		this.memberRepository = memberRepository;
		this.discountPolicy = discountPolicy;
	}
}

 

컴포넌트 스캔할 때 OrderServiceImpl 를 스프링 빈으로 등록이 되면 @Autowired 어노테이션이 부여된 생성자가 있기 때문에 생성자를 호출을 하여 의존성 주입을 한다. 

어떻게? 스프링 빈이 MemberRepositoryDiscountPolicy라는 타입의 빈(Bean)을 찾아서 인자로 받아들여 주입시키고  OrderServiceImpl 빈을 생성

 

즉 스프링은 OrderServiceImpl 빈을 생성할 때 MemberRepositoryDiscountPolicy의 구현체를 찾아와서 해당 인스턴스를 생성자를 통해 주입한다. 

 

 

MemberRepository 구현체 [MemoryMemberRepository]

@Component
public class MemoryMemberRepository implements MemberRepository{ //MemberRepository의 구현체

	
	private static Map<Long, Member> store = new HashMap<>();
	
	@Override
	public void save(Member member) {
		store.put(member.getId(), member);
	}

	@Override
	public Member findById(Long memberId) {
		return store.get(memberId);
	}
}

 

 

 

 

 

2. 수정자 주입 (setter 주입)

 

  • memberRepository , discountPolicy 필드명에 set 붙이고 카멜표기법으로 필드값을 메서드로 통해 직접 수정하기
    • setMemberRepository, setDiscountPolicy
@Component
public class OrderServiceImpl implements OrderService{
	
	private MemberRepository memberRepository; 
	private DiscountPolicy discountPolicy; 
	
	//setter 의존관계 주입
	@Autowired
	public void setMemberRepository(MemberRepository memberRepository) {
		System.out.println("memberRepository = " + memberRepository);
		this.memberRepository = memberRepository;
	}

	@Autowired
	public void setDiscountPolicy(DiscountPolicy discountPolicy) {
		System.out.println("discountPolicy = " + discountPolicy);
		this.discountPolicy = discountPolicy;
	}
 }

 

    * 생성자 필요 없음

[테스트 결과]

 

 

 

  • 특징 (선택, 변경)
    • 선택적으로 의존관계를 주입할 수 있다.
    • @Autowired(required=false) : 원래는 @Autowired 의 기본동작은 주입할 대상이 없으면 오류가 발생하지만 주입할 대상 없이도 동작하게 된다. 
@Autowired(required=false) //의존관계 안해도 됨.
public void setMemberRepository(MemberRepository memberRepository) { }
    • 변경가능성 있는 의존관계 

 

 

 

 

 

3. 필드 주입

  • 이름 그대로 필드에 바로 주입하는 방법 (권장하지 않음)
  • 특징 
    • 코드가 간결해서 외부에 변경이 불가능해 테스트하기가 어렵다.
    • 실제코드와 관련없는 테스트 코드에 사용
  • 예시 
    • memberRepository, discountPolicy 필드앞에 @Autowired 붙이기 
@Component
public class OrderServiceImpl implements OrderService {

    @Autowired
    private MemberRepository memberRepository;
    
    @Autowired
    private DiscountPolicy discountPolicy;
}

 

 

 

 

4. 일반 메서드 주입

  • 일반 메서드를 통해 주입 받을 수 있다.
  • 특징
    • 아무 메서드에 @Autowired 를 붙일 수 있다.
    • 한번에 여러 필드를 주입 받을 수 있다.
    • 그러나 생성자 주입이나 수정자 주입을 대부분 사용하기 때문에 일반 메서드 주입은 일반적으로 사용하지 않는다. 
  • 예시
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;
	}
    
  }

 

 

※ 참고 

OrderServiceImpl 은 스프링 컨테이너가 관리하는 스프링 빈이라서 @Autowired 가 기능한다.
 
( OrderServiceImpl 는 @Component 을 붙였기 때문에 스프링 컨테이너에 의해 빈으로 관리하는 클래스다. )
 
일반 클래스는 @Autowired 를 적용해도 아무 동작을 하지 않는다.

 

 

반응형
LIST

+ Recent posts