티스토리 뷰

백엔드/SPRING MVC

의존관계 자동 주입 방법

거북이의 기술블로그 2024. 8. 21. 19:08
Dependency Injection

 

Injection 방법

  • 생성자 주입
    • 생성자 호출시점에 딱 1번 호출되는 것이 보장됨
    • 불변, 필수 의존관계 가능
@Component
public class BeanTestImpl{

    private final BeanTest beanTest;
    
    // 생성자가 딱 1개일경우 @Autowired 를 생략해도 된다.
    public BeanTestImpl( BeanTest beanTest )
    {
        this.beanTest = beanTest;
    }
}
  • 수정자 주입 (setter)
    • 선택, 변경이 가능하다
@Component
public class BeanTestImpl{

    private final BeanTest beanTest;
    
    @Autowired
    public setBeanTest( BeanTest beanTest )
    {
        this.beanTest = beanTest;
    }
}
  • 필드 주입
    • 바로 주입이 되기 때문에 , 외부에서 접근이 어렵고 스프링이 없으면 테스트하기 어렵다
@Component
public class BeanTestImpl{

    @Autowired
    private final BeanTest beanTest;
    
    
}
  • 일반 메서드 주입
    • 한번에 여러 필드를 주입 받을 수 있다
    • 일반적으로 잘 사용하지 않음
@Component
public class BeanTestImpl{

    private final BeanTest beanTest;
    
    @Autowired
    public void init( BeanTest beanTest )
    {
        this.beanTest = beanTest;
    }
}

 

  • 주로 생성자 주입을 사용한다 ( 주입시점은 딱 1번이면 되기에 필수,불변이어야한다. )

 

@Autowired option ( required )

Default로 "Required= true" 지정되어있기 때문에, 주입할 대상이 없으면 오류를 내뱉음

- 주입할 대상이 없다면, "required = false " 로 두면 대상이 없을경우 NULL이 입력됨

 

 

 

빈이 2개이상 조회될 때 처리

  • 구현체에 지정 (MemoryMemberRepository Vs DBMemberRepository)
    •  @Qualifier ("mainRepository")
    • 구현체가 2개 조회될때 , @Qulifier을 통해 지정가능
    • 만약, @Qulifier("mainRepository")가 타입 체크가 안된다면 -> Annotation을 만들어야한다.
//구현체1
@Component
@Qualifier("mainRepository")
public class DbMemberRepository implements MemberRepository{}

//구현체2
@Component
@Qualifier("memoryMemberRepository")
public class MemoryMemberRepository implements MemberRepository{}


//인터페이스 의존
@Component
public class BeanImpl(){
    
    private final MemberRepository memberRepository; 
    
    @Autowired 
    public BeanImpl(@Qualifier("mainRepository")MemberRepository memberRepository){
    this.memberRepository = memberRepository;
    }

}

 

  • @Qulifier("mainRepository")가 타입 체크 Annotation만들기
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
 ElementType.TYPE, ElementType.ANNOTATION_TYPE})
 @Retention(RetentionPolicy.RUNTIME)
 @Documented
 @Qualifier("mainRepository")
 public @interface MainRepository {
}

@Component
@MainRepository
public class DbMemberRepository implements MemberRepository{}

 

  • @Primary
    • 2개이상 bean이 조회될 때 우선순위를 가짐
//구현체1
@Component
@Primary
public class DbMemberRepository implements MemberRepository{}

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


//인터페이스 의존
@Component
public class BeanImpl(){
    
    private final MemberRepository memberRepository;
    
    @Autowired 
    public BeanImpl(MemberRepository memberRepository){
    // DbMemberRepository가 주입된다.
    this.memberRepository = memberRepository;
    }

}

 

 

  • @Qulifier Vs @Primary 우선순위
    • Qulifier이 더 우선권을 가지게 된다.

 

 

조회할 빈이 다 필요할때 (MAP, LIST)

public class AllBeanTest {
    @Test
    void findAllBean() {
        
        ApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class, DiscountService.class);
        
        DiscountService discountService = ac.getBean(DiscountService.class);
        Member member = new Member(1L, "userA", Grade.VIP);
        int discountPrice = discountService.discount(member, 10000,"fixDiscountPolicy");
        
        assertThat(discountService).isInstanceOf(DiscountService.class);
        assertThat(discountPrice).isEqualTo(1000);
    }
    
    // 구현체 -> FixDiscountPolicy , RateDiscountPolicy
    // discountService관련 코드
    static class DiscountService {
    
        private final Map<String, DiscountPolicy> policyMap;
        private final List<DiscountPolicy> policies;
        
        public DiscountService(Map<String, DiscountPolicy> policyMap, List<DiscountPolicy> policies) {
            this.policyMap = policyMap;
            this.policies = policies;
            System.out.println("policyMap = " + policyMap);
            System.out.println("policies = " + policies);
        }
        
        public int discount(Member member, int price, String discountCode) {
            //map에서 구현체 String key 찾기
            DiscountPolicy discountPolicy = policyMap.get(discountCode);
            System.out.println("discountCode = " + discountCode);
            System.out.println("discountPolicy = " + discountPolicy);
            return discountPolicy.discount(member, price); // 파라미터값 discount 주입
} }
}

 

'백엔드 > SPRING MVC' 카테고리의 다른 글

Bean ( @Scope , Provider )  (0) 2024.08.22
빈 생성시 값 초기화 방법 ( init() )  (0) 2024.08.22
@Component에 관하여...  (0) 2024.08.21
싱글톤 컨테이너  (0) 2024.08.21
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함