@Autowired가 붙었을 때

    @Autowired가 붙었을 때의 동작 공부

    @Autowired는 @ComponentScan과 함께 주로 사용된다. @ComponentScan을 통해 @Component가 붙은 객체들이 모두 생성되어 빈 컨테이너에 저장이 된다. 저장이 완료된 후, 의존관계를 주입하는 단계에서 @Autowired가 붙은 메서드들이 하나씩 호출이 된다. 이 때, 각 메서드의 매개변수에 해당되는 타입이 스프링 빈 컨테이너에서 찾아온 후 의존관계 주입이 된다. 

    순서를 좀 더 간략히 정리해보면 다음과 같을 것 같다.

    1. @ComponentScan이 @Component의 대상인 모든 Class를 읽어온다.
    2. 모든 Class의 생성자를 통해 싱글톤 객체를 하나 생성해서 스프링 컨테이너의 빈 저장소에 저장한다.
    3. 의존관계 주입 단계에서 @Autowired가 붙은 메서드를 하나씩 불러오면서, 필요한 곳의 의존관계를 주입해준다.
    4. 초기화 콜백 메서드를 실행한다. 

    아래에서는 @Autowired를 통해 의존관계를 주입할 때, 경우를 좀 나눠서 생각해보려고 한다. 

     

    1. 생성자가 여러 개 있고, 모두 @Autowired가 붙었을 때


    public class OrderServiceImpl implements OrderService{
    
        private fDiscountPolicy discountPolicy;
        private MemberRepository memberRepository;
    
        @Autowired
        public OrderServiceImpl(DiscountPolicy discountPolicy) {
            System.out.println("OrderServiceImpl.OrderServiceImpl1");
            this.discountPolicy = discountPolicy;
        }
    
        @Autowired
        public OrderServiceImpl(MemberRepository memberRepository){
            System.out.println("OrderServiceImpl.OrderServiceImpl22");
            this.memberRepository = memberRepository;
        }

    위처럼 클래스를 짠 후, @Autowired를 처리하면 오류가 발생한다. 오류 내용은 아래 스크린샷에서 확인할 수 있다. 

    오류는 대략적으로 @Autowired가 생성자가 이미 있는데, 왜 다른 것을 또 호출하냐는 의미인 것 같다. 생각해보면 생성자는 그 객체를 생성할 때 사용되는 것인데, 생성자가 두 번 호출된다는 것은 두 개의 객체가 생성되는 것으로 이해할 수 있다. 즉, 내가 원하는 동작에 맞지 않고 이치에도 맞지 않는다. 그래서 오류가 발생하는 것으로 보인다. 

     

    2. 생성자 1개, 수정자 1개에 각각 @Autowired가 붙어 있을 경우


    @Component
    public class OrderServiceImpl implements OrderService{
    
        private final DiscountPolicy discountPolicy;
        private MemberRepository memberRepository;
    
        @Autowired
        public OrderServiceImpl(DiscountPolicy discountPolicy) {
            System.out.println("OrderServiceImpl.OrderServiceImpl1");
            this.discountPolicy = discountPolicy;
        }
    
        @Autowired
        public void setMemberRepository(MemberRepository memberRepository) {
            this.memberRepository = memberRepository;
        }

    위의 코드는 정상적으로 동작한다. 스프링 빈이 생성되서 빈 컨테이너에 저장된다. 이 때 discountPolicy는 생성자 주입을 통해서 스프링 컨테이너에 있는 빈 값을 찾아서 넣어줄 것이다. memberRepository에는 어떠한 값도 없을 것이다. 이후 의존관계 주입 단계에서 @Autowired 값이 차례차례 불러와질 때, 수정자를 통해서 MemberRepository 타입의 빈의 의존관계가 주입된다. 

     

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

    @RequiredArgsConstruct  (0) 2022.01.11
    Spring MVC : Error 관련  (0) 2022.01.06
    빈 스코프, Provider  (0) 2021.11.12
    빈 생명주기 콜백  (0) 2021.11.12
    빈 등록, 자동? 수동? 선택 기준은?  (0) 2021.11.12

    댓글

    Designed by JB FACTORY