ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 의존관계 자동 주입
    백엔드/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
    Spring Bean (+ Bean Factory)  (0) 2024.08.21
Designed by Tistory.