Skip to main content

의존성

SpringAbout 1 min

원문 : https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-dependenciesopen in new window

전형적인 엔터프라이즈 어플리케이션에서는 단일 객체(또는 스프링에서의 빈)으로 구성되어있지는 않습니다.
아주 간단한 어플리케이션 조차도 최종사용자에게 일관된 어플리케이션으로 보일 수 있도록 함께 동작하는 몇가지 객체를 가지고 있습니다.
다음 절에서 목표를 달성하기 위해 객체가 있는 완전히 구현된 어플리케이션의 독립실행에서 다수의 빈을 정의하는 방법을 설명하겠습니다.

1.4.1 의존성 주입

의존성 주입은 생성자 인수, 팩토리 함수의 인수, 또는 생성되거나 팩토리함수로부터 반환된 이후 객체 인스턴스에 설정된 속성으로만 통해 객체들에 대한 의존성(즉, 동작하는 다른 객체들)을 정의하는 프로세스입니다.
컨테이너는 빈을 만들때 해당 의존성을 주입합니다.
이 프로세스는 근본적으로 클래스 또는 서비스 로케이터 패턴의 직접 구성을 사용하여 자체적으로 의존성의 인스턴스화 또는 위치를 제어하는 빈 자체의 역(따라서 이름은 제어의 역전, Inversion of Control) 입니다.

코드는 DI 개념을 통해 명확해지고, 객체의 의존성이 제공되어질 때 디커플링이 좀더 효율적입니다.
객체는 의존성들을 탐색하지 않고 의존성에 대한 위치나 클래스를 모릅니다.
결론적으로, 특히 의존성이 인터페이스 또는 추상기본클래스에 있을 때 클래스는 테스트하기 더 쉬워지고, 이를 통해 단위테스트에서 스텁 또는 모의 구현을 사용할 수 있습니다.

DI는 두가지 주요 변형을 가지고 있습니다.

생성자 기반 의존성 주입

생성자 기반 DI는 컨테이너가 각각 의존성을 표현하는 다수의 인자를 가진 생성자를 실행하여 완성됩니다.
빈을 생성하기 위해 특정 인자를 가진 정적 팩토리 함수를 호출하는것과 거의 유사하며, 이 논제에서는 생성자와 정적 팩토리 함수가 유사하게 인자를 다룹니다.
아래 예제는 생성자 주입으로 의존성 주입하는 클래스를 보여줍니다.

public class SimpleMovieLister {
    // SimpleMovieLister는 MovieFinder를 의존성로 가지고 있습니다.
    private final MovieFinder movieFinder;
    
    // 생성자를 통해 스프링 컨테이너가 MovieFinder를 주입시켜줍니다.
    public SimpleMovieLister(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
    
    // 실제 주입된 MovieFinder를 사용하는 업무로직은 생략....
}

이 클래스에는 특별한 것이 없는것을 주의 깊게 봐주세요.
컨테이너에 인터페이스나 기본 클래스, 어노테이션을 지정하여 의존성이 없는 단순 POJO 객체입니다.

생성자 인자 처리

생성자 인자 처리의 매칭은 인자 유형을 사용했을 때 발생합니다.
빈 정의의 생성자 인수에 잠재적 모호성이 없다면, 빈 정의에서 생성자 인수가 정의되는 순서는 빈이 인스턴스화 될 때 해당 인수가 적절한 생성자에 전달되는 순서입니다.
아래 클래스를 고려해보겠습니다.

package x, y;

public class ThingOne {
    public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {
        // ...
    }
}

ThingTwoThingThree 클래스는 상속적으로 관련이 없고, 잠재적인 모호성이 없다고 가정하겠습니다.
따라서 다음 구성이 잘 동작하며, <constructor-arg/> 요소에 별도의 생성자 인자 인덱스나 유형을 명시하지 않아도 됩니다.

<beans>
    <bean id="beanOne" class="x.y.ThingOne">
        <constructor-arg ref="beanTwo"/>
        <constructor-arg ref="beanThree"/>
    </bean>
    
    <bean id="beanTwo" class="x.y.ThingTwo"/>
    <bean id="beanThree" class="x.y.ThingThree"/>
</beans>

다른 빈이 참조될 때 유형을 알고 있으면 매칭이 발생됩니다.
(앞의 예와 마찬가지로) <value>true</value> 와 같은 단순 유형이 사용될 때 스프링은 값의 유형을 결정할 수 없고 따라서 도움없이 유형으로 매칭을 할 수 없습니다.
아래 클래스를 고려해보겠습니다.

package examples;

public class ExampleBean {

    // 궁극적인 대답을 계산하기 위한 년도의 수
    private final int years;
    
    // 인생, 우주, 모든 것에 대한 답변
    private final String ultimateAnswer;
    
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}

생성자 인자 타입 매칭

앞의 시나리오에서 컨테이너는 생성자 인수 유형을 type 속성을 사용하여 명시적으로 정의해서 단순한 유형에 대한 타입 매칭을 사용할 수 있습니다.
아래의 예제를 참고하세요.

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg type="int" value="7500000"/>
    <constructor-arg type="java.lang.String" value="42"/>
</bean>

생성자 인자 순번

아래의 예제처럼 index 속성을 사용해서 생성자 인자의 순번을 명시적으로 선언할 수 있습니다.

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg index="0" value="7500000"/>
    <constructor-arg index="1" value="42"/>
</bean>

다수의 단순 값에 대한 모호성을 해결하는것 외에도 생성자가 동일한 유형의 두 인자를 가지고 있으면 인덱스를 지정하면 모호성이 해결됩니다.

Tips

인덱스는 0부터 시작합니다.

생성자 인자 이름

아래 예제에서 보여주는 것 처럼 값의 명확화를 위해 생성자 인자 이름을 사용할 수 있습니다.

<bean id="exampleBean" class="examples.ExampleBean">
    <constructor-arg name="years" value="7500000"/>
    <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

이 작업이 즉시 수행할 수 있도록 명심해야될 것은 스프링이 생성자로부터 인자의 이름으로 찾을 수 있도록 디버그 플래그를 활성화하여 코드를 컴파일 해야하는 것 입니다.
디버그 플래그로 코드를 컴파일 할 수 없거나 원치 않는 경우 @ConstructorProperties JDK 어노테이션을 사용해서 생성자 인자의 이름을 명시적으로 선언할 수 있습니다.
그러면 샘플 클래스는 다음과 같아야 합니다.

package examples;

public class ExampleBean {

    // 생략된 필

    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}

Setter 기반 의존성 주입

종속성 처리 프로세스

의존성 주입 예제

1.4.2 세부적인 의존성과 구성

직접적인 값 (원시형, 문자열 등)

idref 요소

다른 빈에 대한 참조 (협력자)

내부 빈

컬렉션

컬렉션 병합

컬렉션 병합의 한계

Null과 공백 문자열 값

p-네임스페이스의 XML 바로가기

c-네임스페이스의 XML 바로가기

복합속성이름

1.4.3 depends-on 사용하기

1.4.4 지연초기화

1.4.5 자동연결 협력자

자동연결의 한계와 단점

자동연결에서 빈 제외하기

1.4.6 함수 주입

함수 주입 조회

임의 함수 대체