인프런 커뮤니티 질문&답변

세승님의 프로필 이미지
세승

작성한 질문수

스프링 핵심 원리 - 기본편

다양한 의존관계 주입 방법

setter 주입을 private으로 선언해도 의존 주입이 되는 이유

작성

·

364

0

수정자 주입과 관련된 질문이 생겨서 글을 쓰게 되었습니다.

강의에서 setter를 이용한 의존 주입을 할 때는, setter 함수를 public으로 열어놔야한다고 하셨습니다.

만약에 private으로 막아놓으면 어떻게 될지 궁금해서 private으로 막아 놓고 테스트를 돌려보았는데, 여전히 올바르게 의존주입이 되는 결과가 나왔습니다.

아무리 생각해봐도 스프링이 private으로 막혀있는 setter 함수를 호출할 수 없을 것 같은데, 어떻게 올바른 의존 주입이 되는 결과가 나온건지 궁금합니다.

테스트에 사용한 코드는 아래와 같습니다.

// OrderServiceImpl.java
package hello.core.order;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.RateDiscountPolicy;
import hello.core.member.Member;
import hello.core.repository.MemberRepository;
import hello.core.repository.MemoryMemberRepository;

@Component
public class OrderServiceImpl implements OrderService {

    
    private MemberRepository memberRepository;
    private DiscountPolicy discountPolicy;

    // ! setter 주입(setter 주입을 사용하려면 final 키워드를 사용할수 없음)
    @Autowired
    private void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

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

    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);

        return new Order(memberId, itemName, itemPrice, discountPrice);
    }

    // 테스트 용도
    public MemberRepository getMemberRepository() {
        return this.memberRepository;
    }
}


// AutoAppConfigTest.java
package hello.core.scan;

import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import hello.core.AutoAppConfig;
import hello.core.member.MemberService;
import hello.core.order.OrderServiceImpl;
import hello.core.repository.MemoryMemberRepository;

public class AutoAppConfigTest {

    @Test
    void basicScan() {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AutoAppConfig.class);

        OrderServiceImpl orderServiceImpl = ac.getBean(OrderServiceImpl.class);
        System.out.println(orderServiceImpl.getMemberRepository());
    }

}

// AutoAppConfig.java
package hello.core;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;

@Configuration
@ComponentScan(basePackages = "hello.core", basePackageClasses = AutoAppConfig.class, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class))
public class AutoAppConfig {

}

답변 1

0

안녕하세요, 세승 님! 공식 서포터즈 codesweaver 입니다.

이 부분은 자바의 리플렉션 기능을 이용합니다!

private 필드, 메서드 등을 강제로 접근 가능하도록 변경하여 값을 주입하게 됩니다.

아래의 링크를 참조해주세요.

https://stackoverflow.com/questions/34668872/why-autowired-in-spring-does-not-need-setter-method-for-private-instance-variab

감사합니다.

세승님의 프로필 이미지
세승

작성한 질문수

질문하기