의존관계 주입 방법 알아보기

jooog·2022년 5월 7일
0

스프링

목록 보기
25/26
post-thumbnail

💡 의존관계 주입방법

의존관계를 주입하는 방법에는 크게 네가지가 있다. 이 중 가장 많이 사용하고 권장되는 방법은 생성자 주입이다.

  • 생성자 주입
  • 수정자 주입(Setter)
  • 필드 주입
  • 일반 메서드 주입

💡 생성자 주입

생성자 호출 시점에 딱 1번만 호출되며 반드시 값이 할당되어야 하고 할당된 값이 변경되어서는 안되는 경우에 사용한다.

@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;
    }
}

스프링 빈에 OrderServiceImpl이 등록될 때 @Autowired가 붙은 생성자를 확인해서 MemberRepository와 DiscountPolicy를 스프링 컨테이너에서 꺼내 주입해준다.

불변, 필수 의존관계에 사용한다는 말은 곧 값이 변경되어서는 안되고 반드시 값이 할당되어야 한다는 것을 말한다.

✔ @Autowired 생략 가능

@Component
public class OrderServiceImpl implements OrderService{


    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
}

위의 코드에서처럼 생성자가 한개인 경우에는 @Autowired 어노테이션을 생략해도 된다.

✔ Lombok 라이브러리

Lombok 라이브러리의 @RequiredArgsConstructor 어노테이션을 사용하면 final이 붙은 필드를 모아 자동으로 생성자를 만들어준다.

@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService{


     private final MemberRepository memberRepository;
     private final DiscountPolicy discountPolicy;
     
     //test
    public MemberRepository getMemberRepository(){
        return memberRepository;
    }
 }

💡 수정자 주입(Setter)

선택적이고 변경가능성이 있는 의존관계에 사용한다. 생성자를 통해 주입받는 값이 필수값이라면 Setter로 주입받는 값은 선택적이다.

@Component
public class OrderServiceImpl implements OrderService{


    private MemberRepository memberRepository;
    private DiscountPolicy discountPolicy;

    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
        System.out.println("memberRepository = " + memberRepository);
    }

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

    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        System.out.println("1 OrderServiceImpl 호출");
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

Setter를 통해서도 의존관계 주입이 가능하다. 위의 코드에서 보면 생성자와 setter가 동시에 사용된 것을 확인할 수 있다. 이 경우에는 OrderServiceImpl이 스프링 빈에 등록되면서 생성자를 먼저 호출하고 그 이후에 setter 주입을 받는다. 이 경우 생성자를 삭제하고 Setter 주입만 사용하면 된다.

📑출력결과

💡 필드주입

코드가 간결하다는 장점이 있지만 외부에서 변경이 불가능하다는 단점이 있고 DI 프레임워크가 반드시 필요하다. 최근에는 필드 주입을 권장하지 않는다.

@Component
public class OrderServiceImpl implements OrderService{


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


  //test
  public MemberRepository getMemberRepository(){
      return memberRepository;
  }
}

💡 일반 메서드 주입

한번에 여러 필드를 주입받을 수 있다는 장점이 있지만 보통 생성자 주입이나 수정자 주입을 사용하기 때문에 일반적으로 잘 사용하지 않는다.

@Component
public class OrderServiceImpl implements OrderService{


     private MemberRepository memberRepository;
     private DiscountPolicy discountPolicy;

	@Autowired
	public void method(MemberRepository memberRepository, DiscountPolicy discountPolicy){
	this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
}
    

💡 의존관계 주입 옵션처리

✔ @Autowired(required = false)

@Component
public class OrderServiceImpl implements OrderService{


    private MemberRepository memberRepository;
    private DiscountPolicy discountPolicy;

    @Autowired(required = false)
    public void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Autowired
    public void setDiscountPolicy(DiscountPolicy discountPolicy) {
        this.discountPolicy = discountPolicy;
    }

}

기본적으로 @Autowired 어노테이션이 붙으면 의존관계 주입이 필요하다. 하지만 @Autowired(required = false)를 붙여 지정하면 선택적으로 주입할 수 있다.

✔ @Nullable , Optional

스프링 빈에 등록되지 않은 Member 클래스를 주입받는 경우에는 옵션 처리를 해줄 수 있는데 @Nullable 어노테이션을 사용해 스프링빈에 등록된 객체가 없는 경우에는 null을 출력하거나 자바8의 문법인 Optional로 처리하는 방법이 있다.

       @Autowired(required = false)
        public void setBean(Member member){
            System.out.println("member1 = " + member);
        }

        @Autowired
        public void setBean2(@Nullable Member member){
            System.out.println("member2 = " + member);
        }

        @Autowired
        public void setBean3(Optional<Member> member){
            System.out.println("member3 = " + member);
        }

📑출력결과

@Autowired(required = false) 인 경우에는 자동 주입할 대상이 없으면 수정자 메서드 자체가 호출이 되지 않아 아무런 값도 출력되지 않았고 @Nullable 어노테이션이 붙으면 null, Optional로 처리한 경우에는 Optional.empty가 출력된 것을 확인할 수 있다.

0개의 댓글