본문 바로가기

SpringFramework Core - I. IoC 컨테이너/4. 의존성

4.1.2. setter 기반의 의존성 주입

원문: https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-setter-injection

 

 

setter 기반의 의존성 주입은, 컨테이너가 기본 생성자를 호출하거나 매개변수 없는 static 팩토리 메서드를 호출하여 bean을 인스턴스화한 후에 bean의 setter 메소드를 호출함으로써 이루어진다. 

 

다음 예시는 순수한 setter 주입만을 통해 의존성을 주입받을 수 있는 클래스를 보여준다. 이 클래스는 전통적인 자바이다. 컨테이너에 특정된 인터페이스, 클래스 또는 어노테이션에 의존성을 갖지 않는 POJO이다.

public class SimpleMovieLister {

    // SimpleMovieLister는 MovieFinder에 의존성을 갖는다.
    private MovieFinder movieFinder;
    
    // 스프링 컨테이너가 MovieFinder를 주입할 수 있도록 하는 setter 메서드
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    
    // 주입된 MovieFinder를 사용하는 비즈니스 로직은 생략...
}

ApplicationContext는 생성자 기반의 의존성 주입과 setter 기반의 의존성 주입을 지원한다. 또한 생성자 방식을 통해 이미 몇몇 의존성이 주입된 후에도 setter 기반의 의존성 주입을 지원한다. 여러분은 properties를 다른 형식으로 변환해주는 'PropertyEditor' 인스턴스와 함께, BeanDefinition의 형태로 의존성을 설정한다. 하지만 대부분의 스프링 유저들은 이런 클래스들을 직접적으로 사용하지 않는다. 대신 XML bean 정의, @Component/@Controller 등의 어노테이션 또는 자바 기반의 @Configuration 클래스들 안에서 @Bean 메서드를 활용하는 식으로 한다. 이 자원들은 내부적으로 BeanDefinition 인스턴스로 변환된다. 그리고 스프링 IoC 컨테이너 인스턴스 전체를 로딩한다. 

 

 

 생성자 기반 의존성 주입 vs setter 기반 의존성 주입

생성자 기반 의존성 주입과 setter 기반 의존성 주입을 섞어쓸 수 있기 때문에, 생성자 방식을 의무적인 의존성들에 사용하고 setter 메서드나 설정 메서드 방식들을 선택적인 의존성들에 사용하는 것이 가장 좋다. setter 메서드에 @Required 어노테이션을 사용하면, 프로퍼티가 의존성을 필요로하게 된다는 사실을 기억하라. 하지만 생성자 주입 방식은 프로그램적으로 매개변수의 유효성 검증이 되기 때문에 더 선호된다.

스프링 제작진은 보통 생성자 주입 방식을 지지한다. 애플리케이션 컴포넌트들을 변경할 수 없는 객체로 실행하게끔 해주고, 필수적인 의존성들을 null이 아니게끔 보장해주기 때문이다. 게다가 생성자 주입 방식의 컴포넌트는 항상 완전히 초기화된 상태에서 클라이언트(호출한) 코드에게 반환된다. 여담으로 많은 숫자의 생성자 매개변수들에서는 나쁜 코드의 냄새가 난다. 클래스가 너무 많은 책임을 가지고 있으며, 적절한 관심사 세분을 통해 리팩토링되어야함을 암시하기 때문이다. 

setter 주입 방식은 주로 선택적인 의존성 주입에 사용되는 것이 좋다. 그리고 그런 의존성들은 클래스 내부에서 적절한 기본값을 할당 받을 수 있어야 한다. 그렇지 않으면, 의존성을 사용하는 곳에서는 모두 not-null 체크를 수행해야만 하기 때문이다. setter 주입 방식의 한가지 장점은, setter 메서드가 설정 변경이나 재주입에 대해 객체를 변경 가능하도록 만든다는 점이다. 그러므로 JMX MBeans를 통한 관리가 setter 주입 방식에서는 강력한 use case가 된다.

특정 클래스에게 가장 유용한 의존성 주입 스타일을 사용하라. 때때로 소스가 공개되지 않은 third-party 클래스들과 함께 해야할 때는 여러분이 선택을 해야한다. 예를 들어, third-party 클래스가 setter 메서드를 노출하지 않는다면 생성자 주입 방식이 유일한 의존성 주입이 형식이 될 것이다.