개발일기장

Spring 공부 04. 의존관계주입 본문

Spring Boot

Spring 공부 04. 의존관계주입

게슬 2023. 7. 5. 21:37
728x90

Spring에서 의존관계를 주입 할 때 여러가지 방법이 있음

 

1. 생성자 주입

    @Autowired 
    //생성자가 하나면 Autowired 안 사용해도 되고
    // 2개 이상이면 @Autowired 지정해 줘야함.
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

해당 방식을 사용 할 때에는 각각의 필드에 private final을 설정하는게 좋다.


2. 필드 주입

 

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

이렇게 사용 할 수는 있지만 권장되는 방식이 아님.

테스트 할 때에는 상관이 없지만.. 


3. setter 주입

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

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

이렇게 사용해도 된다.


4. method주입

    @Autowired // 이것도 안좋아.
    void init(MemberRepository memberRepository, DiscountPolicy discountPolicy){
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

그냥 아무 method에 @Autowired를 넣어도 되는데 진자 사용하면 안되는 방식이긴함.


그다음에 @Configuration 에 직접 @Bean을 설정하는 방식도 있음

모든 주입은 순서가 보장되지 않음. 어짜피 Singleton이기 때문에 상관은 없는 방식임


그리고 의존관계 주입을 할 때에 여러가지 Option을 설정 할 수 있음.

        @Autowired(required = false) // 기본값은 True임. -> 찾을 수 없으면 Error
        public void setNoBean1(Member noBean1){
            System.out.println("noBean1 = " + noBean1);
            // Member는 Spring이 관리하는 Bean이 아님.
            // required = false -> 의존관계가 없으면 호출이 되지 않는다.
        }

        @Autowired
        public void setNoBean2(@Nullable Member noBean2){
            System.out.println("noBean2 = " + noBean2);
            // 호출은 되는데 의존관계가 없으면 그냥 Null로 해준다.
        }

        @Autowired
        public void setNoBean3(Optional<Member> noBean3){
            System.out.println("noBean3 = " + noBean3);
            //호출은 되는데 의존관계가 없으면 그냥 Optioanl로 지정 해준다.
        }

이런 방법들이 있다.


동일한 Type의 Bean이 2개 이상일 때

1. Interface type이 구체타입 직접 주입하기

이거는 설명 안해도 될거같음.

2. Qualify("{bean name}")

@Component
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy

@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy

이렇게 해두고

public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy)

직접 넣어주면 됨

3. Primary

@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy

아니면 Primary Annotation 달아두면 이게 1순위임.


같은이름의 Bean이 2개 이상일 때 Map이나 List의 Construct가 있으면 그걸 다 주입해준다. 

        private final Map<String, DiscountPolicy> policyMap;
        private final List<DiscountPolicy> policyList;


         public DiscountService(Map<String, DiscountPolicy> policyMap, List<DiscountPolicy> policyList) {
            //Map, List로 받으면 그 Interface에 해당하는 모든 Bean이 주입된다.
            this.policyMap = policyMap;
            this.policyList = policyList;

            System.out.println("policyMap = " + policyMap);
            System.out.println("policyList = " + policyList);
        }

그리고 해당 Bean의 호출은 Map.get("String")으로 해주면 된다..

List는 그냥 Instance of나 find사용하면 되지 않을까..?

 

// method
        public int discount(Member member, int price, String discountCode) {
            DiscountPolicy discountPolicy = policyMap.get(discountCode);
            return discountPolicy.discount(member, price);
        }

// 사용
int discountPrice = discountService.discount(member, 15000, "fixDiscountPolicy");
728x90

'Spring Boot' 카테고리의 다른 글

Spring 공부 06. singleton, prototype  (0) 2023.07.12
Spring 공부 05. Bean Life Cycle  (0) 2023.07.10
Spring 공부 03. @Bean주입  (0) 2023.07.04
Spring 공부 02. 스프링 컨테이너  (0) 2023.07.01
Spring 공부 01. Configuration, Bean  (0) 2023.06.28
Comments