개발/Spring

(스프링 기본) 18 - 다양한 의존관계 주입 방법 (생성자, 수정자, 필드, 일반 메서드)

개발하는 인사담당자 2024. 10. 28. 09:33

■ 의존관계 주입 4가지

1. 생성자 주입

2. 수정자 주입(setter 주입)

3. 필드 주입

4. 일반 메서드 주입

 

■ 생성자 주입

- 생성자를 통해 의존 관계 주입하는 방법

- 생성자 호출 시점 딱 1번만 호출되는 것이 보장된다.

- 불변, 필수 의존관계에 사용

 

@Component
public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

 

생성자에 있는 값은 무조건 넣어주는 것이 관례이다.

따라서 final 로 처리하여 무조건 값을 넣도록 처리한다. 

 

★ 생성자가 딱 1개만 있으면 @Autowired 를 생략해도 자동 주입된다. (스프링 빈에만 해당)

 

■ 수정자 주입(setter 주입)

 

@Component
public class OrderServiceImpl implements OrderService {

    private  MemberRepository memberRepository;
    private  DiscountPolicy discountPolicy;

    @Autowired
    public void setDiscountPolicy(DiscountPolicy discountPolicy) {
        System.out.println("discountPolicy = " + discountPolicy);
        this.discountPolicy = discountPolicy;
    }

    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
        System.out.println("memberRepository = " + memberRepository);
        this.memberRepository = memberRepository;
    }

 

다음과 같이 set 메서드를 통해서 해당 메서드에 @Autowired 를 붙여,

setter 생성자를 주입해도 동일한 값이 나온다. 

 

생성자 주입의 경우, OrderServiceImpl 객체를 생성할 때 생성자를 불러야 함으로 

빈을 등록함과 동시에 주입이 이루어진다. 

 

setter 의 경우에는 빈을 등록하고 의존관계 주입 시 이루어진다. 

 

* 수정자 주입 특징

- 선택, 변경 가능성이 있는 의존관계에서 사용

- 자바빈프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법 

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

 

@Autowired 주입 대상이 없으면 오류가 발생한다. 

따라서 주입할 대상이 없어도 동작하고자 한다면 required = false 처리하면 된다. 

 

※ 자바빈 프러퍼티(=메서드로 접근하여 필드값 변경)

: 자바는 과거부터 필드 값을 직접 변경하지 않고 setXxx, getXxx 라는 메서드로 수정했는데

이를 자바빈 프로퍼티라고 부른다.

 

3. 필드 주입

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

 

의존관계를 바로 필드에 넣어주는 것이다.

 

- 외부에서 변경이 불가능해서 테스트 하기 힘든 치명적 단점이 있다. 

- DI 프레임워크가 없으면 아무것도 할 수 없다. 

- 만약 사용하려고 하면 그 값을 넣어주는 setter 를 또 넣어줘야 함으로 그럴바엔 setter 주입이 낫다.

 

@SpringBootTest
class CoreApplicationTests {

    @Autowired
    OrderService orderService;

    @Test
    void contextLoads() {
       orderService.xxx
    }
}

 

다음과 같이 애플리케이션 실제 코드와 관계 없는 스프링 테스트 코드를 진행할 때는 사용하기도 한다. 

 

@Configuration
@ComponentScan(
        excludeFilters= @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Configuration.class)
)
public class AutoAppConfig {

    @Autowired MemberRepository memberRepository;
    @Autowired DiscountPolicy discountPolicy;

    @Bean
    OrderService orderService() {
        return new OrderServiceImpl(memberRepository, discountPolicy);
    }

    @Bean(name = "memoryMemberRepository")
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}

 

또는 스프링 설정 목적으로 하는 @Configuration 같은 곳에서는 특별한 용도로 사용한다.

왜냐하면 AutoAppConfig 는 스프링 코드에서만 사용할 것이기 때문이다. 

 

4. 일반 메서드 주입

@Autowired
public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
}

 

- 일반 메서드 통해서 주입 받을 수 있다. 

- 한 번에 여러 필드 주입 받을 수 있다.

- 일반적으로 잘 사용하지 않는다.

 

※ 의존관계 자동 주입은 스프링 컨테이너가 관리하는 스프링 빈이어야 동작한다.

그렇지 않은 Member 같은 클래스에서 @Autowired 코드를 적용해도 아무 작동 안한다.

 

출처 : 김영한 스프링 핵심 원리 - 기본편

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B

 

스프링 핵심 원리 - 기본편 강의 | 김영한 - 인프런

김영한 | 스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., 스프링 핵심 원리를 이해하고, 성장하는 백엔드 개발자가 되어보

www.inflearn.com