Note-Taking / / 2024. 9. 3. 17:08

Autowired 어노테이션 사용 방법 정리

@Autowired 어노테이션 사용 방법

 

1. 생성자 주입

@Autowired 어노테이션은 클래스의 생성자에 붙여서 의존성을 주입할 수 있습니다. 예를 들어 아래 코드를 보세요:

public class MovieRecommender {

    private final CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...
}

Spring Framework 4.3 버전부터는 클래스에 생성자가 하나만 있을 경우 @Autowired를 생략해도 됩니다. 그러나 생성자가 여러 개 있을 경우 기본 생성자가 없으면 하나 이상의 생성자에 @Autowired를 붙여서 어떤 생성자를 사용할지 알려줘야 합니다. 생성자 선택에 대한 자세한 내용은 생성자 해결에 대한 논의를 참고하세요.

 

2. 세터 주입

@Autowired를 세터 메서드에 적용하여 의존성을 주입할 수도 있습니다. 아래 예시를 보세요:

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}

3. 메서드 주입

@Autowired는 메서드 이름과 관계없이 임의의 이름을 가진 메서드와 여러 개의 인자를 가진 메서드에도 적용할 수 있습니다. 아래는 예시입니다:

public class MovieRecommender {

    private MovieCatalog movieCatalog;
    private CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(MovieCatalog movieCatalog,
            CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...
}

4. 필드 주입

@Autowired 어노테이션을 클래스의 필드에 직접 붙여서 의존성을 주입할 수 있습니다. 예를 들어:

public class MovieRecommender {

    private final CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    private MovieCatalog movieCatalog;

    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...
}

이 경우, 필드에 직접 의존성을 주입하고, 생성자 주입과 혼합하여 사용할 수 있습니다.

 

5. 자체 참조

Spring Framework 4.3부터는 @Autowired가 자기 자신을 참조하는 것도 허용합니다. 하지만 자기 자신을 참조하는 것은 최후의 수단으로 사용하는 것이 좋습니다 (예: 트랜잭션 프록시를 통해 동일한 인스턴스의 다른 메서드를 호출하는 경우). 이러한 경우에는 영향을 받는 메서드를 별도의 델리게이트 빈으로 분리하는 것이 좋습니다.

6. 배열 및 컬렉션 주입

@Autowired를 사용하여 특정 타입의 모든 빈을 배열이나 컬렉션으로 주입할 수 있습니다. 예를 들어:

public class MovieRecommender {

    @Autowired
    private MovieCatalog[] movieCatalogs;

    // ...
}

같은 방식으로 타입이 지정된 컬렉션에도 주입할 수 있습니다:

public class MovieRecommender {

    private Set<MovieCatalog> movieCatalogs;

    @Autowired
    public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
        this.movieCatalogs = movieCatalogs;
    }

    // ...
}

대상 빈들이 org.springframework.core.Ordered 인터페이스를 구현하거나 @Order 또는 표준 @Priority 어노테이션을 사용하면 배열이나 리스트의 순서를 특정할 수 있습니다. 그렇지 않으면 해당 빈 정의의 등록 순서를 따르게 됩니다.

 

7. Map 주입

타입이 String인 키를 사용하는 Map 인스턴스도 주입할 수 있습니다. Map 값에는 예상되는 타입의 모든 빈이 포함되며, 키는 해당 빈 이름이 됩니다. 예시:

public class MovieRecommender {

    private Map<String, MovieCatalog> movieCatalogs;

    @Autowired
    public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
        this.movieCatalogs = movieCatalogs;
    }

    // ...
}

8. 의존성 선택적 주입

기본적으로 자동 주입은 주입 지점에 적합한 후보 빈이 없으면 실패합니다. 배열, 컬렉션, 또는 맵의 경우 하나 이상의 요소가 일치해야 합니다. @Autowired 어노테이션의 required 속성을 false로 설정하면, 일치하는 빈이 없어도 오류가 발생하지 않고 주입이 생략됩니다:

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Autowired(required = false)
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // ...
}

이 경우, 필수적이지 않은 메서드는 주입 대상이 없으면 호출되지 않으며, 필수적이지 않은 필드는 기본값으로 남게 됩니다.

 

9. Optional 및 @Nullable 사용

Optional을 사용하여 특정 의존성이 선택적임을 표현할 수 있습니다:

public class SimpleMovieLister {

    @Autowired
    public void setMovieFinder(Optional<MovieFinder> movieFinder) {
        ...
    }
}

Spring Framework 5.0부터는 @Nullable 어노테이션도 사용할 수 있습니다. 예를 들어:

public class SimpleMovieLister {

    @Autowired
    public void setMovieFinder(@Nullable MovieFinder movieFinder) {
        ...
    }
}

10. *일반적인 스프링 라이프사이클 콜백 및 Aware 인터페이스

@Autowired는 BeanFactory, ApplicationContext, Environment, ResourceLoader, ApplicationEventPublisher, MessageSource와 같은 인터페이스에도 적용할 수 있습니다. 이러한 인터페이스와 그 확장된 인터페이스들은 특별한 설정 없이도 자동으로 해결됩니다. 예를 들어 ApplicationContext를 주입하는 방법은 다음과 같습니다:

public class MovieRecommender {

    @Autowired
    private ApplicationContext context;

    public MovieRecommender() {
    }

    // ...
}

@Autowired, @Inject, @Value, 및 @Resource 어노테이션은 Spring BeanPostProcessor 구현에서 처리됩니다. 이는 이러한 어노테이션을 BeanPostProcessor나 BeanFactoryPostProcessor 타입 내에서 사용할 수 없음을 의미합니다. 이러한 타입들은 XML이나 Spring @Bean 메서드를 통해 명시적으로 ‘연결’되어야 합니다.

 

@Primary를 사용한 애노테이션 기반 자동 주입의 세부 조정

 

타입으로 자동 주입(autowiring)을 할 때는 종종 여러 후보 빈이 존재할 수 있기 때문에, 선택 과정을 더 세밀하게 제어할 필요가 있습니다. 이를 달성하는 한 가지 방법은 Spring의 @Primary 애노테이션을 사용하는 것입니다. @Primary는 특정 빈이 단일 값의 의존성에 자동으로 주입될 때 여러 후보 중 우선권을 가져야 한다는 것을 나타냅니다. 후보 중에서 하나의 주(primary) 빈만 존재한다면, 그 빈이 자동으로 주입되는 값이 됩니다.

 

다음은 firstMovieCatalog를 주(primary) MovieCatalog로 정의하는 예시 구성입니다:

@Configuration
public class MovieConfiguration {

    @Bean
    @Primary
    public MovieCatalog firstMovieCatalog() { 
        // ... 
    }

    @Bean
    public MovieCatalog secondMovieCatalog() { 
        // ... 
    }

    // ...
}

위와 같은 구성을 사용하면, 다음과 같은 MovieRecommenderfirstMovieCatalog로 자동 주입됩니다:

public class MovieRecommender {

    @Autowired
    private MovieCatalog movieCatalog;

    // ...
}

해당 빈 정의는 다음과 같습니다:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <bean class="example.SimpleMovieCatalog" primary="true">
        <!-- 이 빈에 필요한 의존성 주입 -->
    </bean>

    <bean class="example.SimpleMovieCatalog">
        <!-- 이 빈에 필요한 의존성 주입 -->
    </bean>

    <bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>

이렇게 하면 MovieRecommender 클래스의 movieCatalog 필드는 firstMovieCatalog 빈으로 주입됩니다. 이는 @Primary 애노테이션을 사용하여 firstMovieCatalog 빈이 우선적으로 선택되었기 때문입니다.

 

@Qualifier를 사용한 애노테이션 기반 자동 주입 세부 조정

 

@Primary는 여러 인스턴스 중 하나의 주(primary) 후보를 결정할 수 있는 경우, 타입을 이용한 자동 주입에 효과적인 방법입니다. 그러나 더 세부적인 제어가 필요할 때는 Spring의 @Qualifier 애노테이션을 사용할 수 있습니다. @Qualifier를 사용하면 특정 인수와 관련된 자격 값을 지정하여 타입 매칭을 좁힐 수 있으며, 이를 통해 각 인수에 대해 특정 빈을 선택할 수 있습니다. 가장 간단한 경우, 이는 다음 예제에서와 같이 단순한 설명 값일 수 있습니다:

public class MovieRecommender {

    @Autowired
    @Qualifier("main")
    private MovieCatalog movieCatalog;

    // ...
}

또한, @Qualifier 애노테이션을 개별 생성자 인수나 메서드 매개변수에 지정할 수도 있습니다. 다음은 그 예제입니다:

public class MovieRecommender {

    private final MovieCatalog movieCatalog;
    private final CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public void prepare(@Qualifier("main") MovieCatalog movieCatalog,
                        CustomerPreferenceDao customerPreferenceDao) {
        this.movieCatalog = movieCatalog;
        this.customerPreferenceDao = customerPreferenceDao;
    }

    // ...
}

다음 예제는 해당 빈 정의를 보여줍니다:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <bean class="example.SimpleMovieCatalog">
        <qualifier value="main"/> 
        <!-- 이 빈에 필요한 의존성 주입 -->
    </bean>

    <bean class="example.SimpleMovieCatalog">
        <qualifier value="action"/> 
        <!-- 이 빈에 필요한 의존성 주입 -->
    </bean>

    <bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>

main 자격 값을 가진 빈은 동일한 값으로 자격이 지정된 생성자 인수와 연결됩니다.

action 자격 값을 가진 빈도 동일하게 연결됩니다.

 

기본 매칭으로, 빈 이름은 기본 자격 값으로 간주됩니다. 따라서 빈을 정의할 때, 내장된 <qualifier> 요소 대신 main이라는 ID를 사용하면 동일한 매칭 결과를 얻을 수 있습니다. 하지만 @Autowired는 기본적으로 타입에 의한 주입에 관한 것이며, 선택적 의미 자격자를 포함합니다. 즉, 자격자 값은 좁히기 의미를 가지며, 고유한 빈 ID를 표현하는 것은 아닙니다. 좋은 자격자 값으로는 main, EMEA, persistent 등이 있으며, 이는 빈 ID와 독립적인 특정 구성 요소의 특성을 나타냅니다.

 

자격자는 타입이 지정된 컬렉션에도 적용됩니다. 예를 들어, Set<MovieCatalog>와 같은 경우입니다. 이 경우, 선언된 자격자에 따라 매칭되는 모든 빈이 컬렉션으로 주입됩니다. 이는 자격자가 고유할 필요가 없다는 것을 의미합니다. 대신, 자격자는 필터링 기준을 구성합니다. 예를 들어, action이라는 자격 값을 가진 여러 MovieCatalog 빈을 정의할 수 있으며, 이들은 모두 @Qualifier("action")으로 주석된 Set<MovieCatalog>에 주입됩니다.

 

타입 매칭 후보 내에서 자격자 값을 사용하여 타겟 빈 이름과 대조하는 것은 주입 지점에서 @Qualifier 애노테이션이 필요하지 않습니다. 다른 해결 지표(예: 자격자 또는 주(primary) 마커)가 없는 경우, Spring은 주입 지점 이름(즉, 필드 이름이나 매개변수 이름)을 타겟 빈 이름과 대조하여 동일한 이름의 후보를 선택합니다. 버전 6.1부터는 이 작업에 -parameters 자바 컴파일러 플래그가 필요합니다.

 

이름으로 주입하기 위한 대안으로, JSR-250 @Resource 애노테이션을 고려할 수 있습니다. 이는 고유한 이름으로 특정 타겟 구성 요소를 식별하는 데 사용되며, 매칭 과정에서 선언된 타입은 중요하지 않습니다. @Autowired는 다소 다른 의미를 가지며, 후보 빈을 타입으로 선택한 후 지정된 문자열 자격자 값만 해당 타입으로 선택된 후보 내에서 고려됩니다(예: 동일한 자격자 라벨로 표시된 빈에 대해 account 자격자와 매칭).

 

자체적으로 컬렉션, 맵, 또는 배열 타입으로 정의된 빈의 경우, @Resource는 고유한 이름으로 특정 컬렉션 또는 배열 빈을 참조하는 데 적합한 솔루션입니다. 그러나 4.3 버전부터는, 요소 타입 정보가 @Bean 반환 타입 서명 또는 컬렉션 상속 계층 구조에서 유지되는 한, Spring의 @Autowired 타입 매칭 알고리즘을 통해 컬렉션, 맵, 배열 타입도 매칭할 수 있습니다. 이 경우, 앞서 설명한 것처럼 동일한 타입의 컬렉션 중에서 선택하기 위해 자격자 값을 사용할 수 있습니다.

 

4.3 버전부터 @Autowired는 자기 참조도 고려합니다(즉, 현재 주입된 빈에 대한 참조). 자기 참조는 예외적인 경우로, 일반적인 종속성이 항상 우선합니다. 따라서 자기 참조는 일반적인 후보 선택에 참여하지 않으며, 주(primary)로 간주되지도 않습니다. 실제로, 자기 참조는 항상 우선순위가 가장 낮습니다. 일반적으로 자기 참조는 마지막 수단으로 사용해야 합니다(예: 트랜잭션 프록시를 통해 동일한 인스턴스의 다른 메서드를 호출하는 경우). 이러한 상황에서는 영향을 받는 메서드를 별도의 대리 빈으로 분리하는 것을 고려하십시오. 대안으로 @Resource를 사용할 수 있으며, 이를 통해 현재 빈의 고유한 이름으로 프록시를 다시 얻을 수 있습니다.

 

동일한 구성 클래스에서 @Bean 메서드의 결과를 주입하려고 하는 시도는 사실상 자기 참조 시나리오로 간주됩니다. 이러한 참조를 실제로 필요로 하는 메서드 서명에서 지연된 방식으로 해결하거나, 영향을 받는 @Bean 메서드를 static으로 선언하여 포함된 구성 클래스 인스턴스와 그 생명주기에서 분리하십시오. 그렇지 않으면, 이러한 빈은 예외 처리 단계에서만 고려되며, 다른 구성 클래스의 매칭된 빈이 주(primary) 후보로 선택됩니다(사용 가능한 경우).

 

@Autowired는 필드, 생성자, 다중 인수 메서드에 적용되며, 매개변수 수준에서 자격자 애노테이션을 통해 좁힐 수 있습니다. 반면, @Resource는 필드와 단일 인수를 가진 빈 속성 설정 메서드에서만 지원됩니다. 따라서 주입 대상이 생성자 또는 다중 인수 메서드인 경우 자격자를 사용하는 것이 좋습니다.

 

사용자 정의 자격자 애노테이션을 생성할 수도 있습니다. 이를 위해 애노테이션을 정의하고 정의 내에서 @Qualifier 애노테이션을 제공합니다. 다음은 그 예제입니다:

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {
    String value();
}

이제 다음 예제와 같이 자동 주입할 필드 및 매개변수에 사용자 정의 자격자를 제공할 수 있습니다:

public class MovieRecommender {

    @Autowired
    @Genre("Action")
    private MovieCatalog actionCatalog;

    private MovieCatalog comedyCatalog;

    @Autowired
    public void setComedyCatalog(@Genre("Comedy") MovieCatalog comedyCatalog) {
        this.comedyCatalog = comedyCatalog;
    }

    // ...
}

다음으로, 후보 빈 정의에 대한 정보를 제공할 수 있습니다. <bean/> 태그의 하위 요소로 <qualifier/> 태그를 추가한 다음, 사용자 정의 자격자 애노테이션과 일치하도록 타입과 값을 지정할 수 있습니다. 타입은 애노테이션의 완전한 클래스 이름과 일치합니다. 대안으로, 이름 충돌의 위험이 없는 경우 단순히 클래스 이름만 사용할 수 있습니다. 다음 예제는 두 가지 접근 방식을 모두 보여줍니다:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/
              xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <bean class="example.SimpleMovieCatalog">
        <qualifier type="Genre" value="Action"/>
        <!-- 이 빈에 필요한 의존성 주입 -->
    </bean>

    <bean class="example.SimpleMovieCatalog">
        <qualifier type="example.Genre" value="Comedy"/>
        <!-- 이 빈에 필요한 의존성 주입 -->
    </bean>

    <bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>

위 XML 예제에서 <qualifier/> 태그를 사용하여 Genre 타입의 자격자와 각각 “Action”과 “Comedy” 값을 정의했습니다. 이는 자격자 값이 일치하는 빈이 각각의 필드나 메서드 인수에 주입되도록 합니다.

 

제네릭을 오토와이어링 한정자로 사용하기

 

@Qualifier 어노테이션 외에도, Java 제네릭 타입을 암시적인 한정자로 사용할 수 있습니다. 예를 들어, 아래와 같은 설정이 있다고 가정해 봅시다:

@Configuration
public class MyConfiguration {

    @Bean
    public StringStore stringStore() {
        return new StringStore();
    }

    @Bean
    public IntegerStore integerStore() {
        return new IntegerStore();
    }
}

위에서 정의한 StringStoreIntegerStore 빈이 제네릭 인터페이스를 구현한다고 가정해 봅시다. (즉, Store<String>Store<Integer>를 구현하는 경우입니다.) 이제 Store 인터페이스를 @Autowire할 때, 제네릭 타입이 한정자로 사용될 수 있습니다. 예시는 다음과 같습니다:

@Autowired
private Store<String> s1; // <String> 한정자, stringStore 빈을 주입

@Autowired
private Store<Integer> s2; // <Integer> 한정자, integerStore 빈을 주입

제네릭 한정자는 리스트, Map 인스턴스, 그리고 배열을 오토와이어링할 때도 적용됩니다. 아래의 예제는 제네릭 리스트를 오토와이어링하는 방법을 보여줍니다:

// <Integer> 제네릭을 가진 모든 Store 빈을 주입
// Store<String> 빈은 이 리스트에 포함되지 않음
@Autowired
private List<Store<Integer>> s;

 

CustomAutowireConfigurer 사용하기

 

CustomAutowireConfigurerBeanFactoryPostProcessor의 일종으로, Spring의 @Qualifier 어노테이션으로 어노테이트되지 않은 경우에도 자신만의 커스텀 한정자(qualifier) 어노테이션 타입을 등록할 수 있게 해줍니다. 아래 예제는 CustomAutowireConfigurer를 사용하는 방법을 보여줍니다:

<bean id="customAutowireConfigurer"
        class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
    <property name="customQualifierTypes">
        <set>
            <value>example.CustomQualifier</value>
        </set>
    </property>
</bean>

AutowireCandidateResolver는 다음과 같은 방식으로 오토와이어링할 후보 빈을 결정합니다:

 

1. 각 빈 정의의 autowire-candidate 값.

2. <beans/> 요소에 사용 가능한 default-autowire-candidates 패턴.

3. @Qualifier 어노테이션의 존재 여부 및 CustomAutowireConfigurer에 등록된 모든 커스텀 어노테이션.

 

여러 개의 빈이 오토와이어링할 후보로 자격이 있는 경우, “primary” 빈을 결정하는 방법은 다음과 같습니다: 후보 중 하나의 빈 정의에 primary 속성이 true로 설정된 경우, 해당 빈이 선택됩니다.

 

 

 

 

 

 

 

 

Spring은 @Resource 어노테이션(Jakarta EE의 JSR-250 표준에 해당하는 jakarta.annotation.Resource)을 사용하여 필드나 setter 메서드에 의존성을 주입할 수 있습니다. 이 패턴은 보통 Jakarta EE에서 자주 사용되며, JSF-managed beans나 JAX-WS 엔드포인트 등에서 볼 수 있습니다. Spring에서는 이 패턴을 Spring-managed 객체에도 지원합니다.

 

@Resource 어노테이션에는 name이라는 속성이 있습니다. 기본적으로, Spring은 이 속성 값을 주입할 빈의 이름으로 해석합니다. 즉, name 속성은 주입할 빈의 이름을 지정하는데 사용되며, 아래 예제와 같이 사용됩니다:

public class SimpleMovieLister {

	private MovieFinder movieFinder;

	@Resource(name="myMovieFinder") 
	public void setMovieFinder(MovieFinder movieFinder) {
		this.movieFinder = movieFinder;
	}
}

 

 

이 코드에서는 @Resource(name="myMovieFinder") 어노테이션이 있는 setMovieFinder 메서드에 myMovieFinder라는 이름을 가진 빈이 주입됩니다.

 

만약 name 속성이 명시적으로 지정되지 않은 경우, 기본 이름은 필드 이름이나 setter 메서드 이름에서 파생됩니다. 필드의 경우, 필드 이름이 기본 이름으로 사용되며, setter 메서드의 경우, 해당 메서드가 다루는 프로퍼티의 이름이 기본 이름으로 사용됩니다. 아래 예제에서는 빈 이름이 movieFinder인 빈이 setter 메서드에 주입됩니다:

 

public class SimpleMovieLister {

	private MovieFinder movieFinder;

	@Resource
	public void setMovieFinder(MovieFinder movieFinder) {
		this.movieFinder = movieFinder;
	}
}

 

 

위의 경우 @Resource에 지정된 이름이 없으므로, Spring은 movieFinder라는 이름의 빈을 주입하게 됩니다.

 

Spring에서 @Resource 어노테이션은 주로 특정 이름의 빈을 주입할 때 사용되며, 이는 주입할 빈의 타입을 기준으로 한 @Autowired와는 다릅니다. 특히 @Resource 어노테이션은 ApplicationContext, BeanFactory, ResourceLoader, ApplicationEventPublisher, MessageSource와 같은 특정 타입의 인터페이스들을 잘 인식하고 적절히 주입합니다.

 

예를 들어, 다음 예제에서 customerPreferenceDao 필드는 CustomerPreferenceDao 타입의 빈 중 이름이 “customerPreferenceDao”인 빈을 먼저 찾고, 없다면 기본적으로 타입에 맞는 빈을 찾아 주입합니다:

public class MovieRecommender {

	@Resource
	private CustomerPreferenceDao customerPreferenceDao;

	@Resource
	private ApplicationContext context; 

	public MovieRecommender() {
	}

	// ...
}

 

위 코드에서 context 필드는 ApplicationContext 타입으로 주입됩니다. @Resource는 이름 기반으로 우선 빈을 찾으며, 만약 이름을 지정하지 않으면 타입을 기준으로 자동 주입됩니다.

 

 

 

Spring의 @Value 어노테이션을 사용하여 외부에서 설정된 프로퍼티 값을 주입하는 방법에 대해 설명합니다.

 

@Value를 사용한 프로퍼티 값 주입

 

@Value는 보통 외부에서 설정된 프로퍼티 값을 주입하는 데 사용됩니다. 예를 들어, 다음과 같은 클래스가 있을 때:

@Component
public class MovieRecommender {

    private final String catalog;

    public MovieRecommender(@Value("${catalog.name}") String catalog) {
        this.catalog = catalog;
    }
}

이 클래스에서는 @Value("${catalog.name}")을 사용하여 catalog라는 이름의 프로퍼티 값을 주입합니다. 이 프로퍼티는 다음과 같이 설정된 application.properties 파일에서 정의될 수 있습니다:

catalog.name=MovieCatalog

이 경우, catalog 필드에는 MovieCatalog라는 값이 주입됩니다.

 

프로퍼티 값이 없는 경우 기본값 설정

 

만약 프로퍼티 값이 설정되지 않은 경우 기본값을 설정하고 싶다면, 다음과 같이 @Value 어노테이션에 기본값을 지정할 수 있습니다:

@Component
public class MovieRecommender {

    private final String catalog;

    public MovieRecommender(@Value("${catalog.name:defaultCatalog}") String catalog) {
        this.catalog = catalog;
    }
}

이 예에서는 catalog.name 프로퍼티가 없을 경우 defaultCatalog가 기본값으로 주입됩니다.

 

SpEL(Expression Language)을 사용한 동적 값 주입

 

@Value 어노테이션에는 SpEL(Spring Expression Language)을 사용할 수도 있습니다. SpEL을 사용하면 런타임 시 동적으로 값을 계산할 수 있습니다. 예를 들어:

@Component
public class MovieRecommender {

    private final String catalog;

    public MovieRecommender(@Value("#{systemProperties['user.catalog'] + 'Catalog'}") String catalog) {
        this.catalog = catalog;
    }
}

위 코드는 시스템 프로퍼티 user.catalog의 값을 가져와 Catalog라는 문자열을 추가한 값을 주입합니다.

 

복잡한 데이터 구조 주입

 

SpEL을 사용하여 복잡한 데이터 구조도 주입할 수 있습니다. 예를 들어, 맵을 주입하려면 다음과 같이 할 수 있습니다:

@Component
public class MovieRecommender {

    private final Map<String, Integer> countOfMoviesPerCatalog;

    public MovieRecommender(
            @Value("#{{'Thriller': 100, 'Comedy': 300}}") Map<String, Integer> countOfMoviesPerCatalog) {
        this.countOfMoviesPerCatalog = countOfMoviesPerCatalog;
    }
}

여기서 countOfMoviesPerCatalog 필드는 Thriller가 100, Comedy가 300이라는 값을 가진 맵이 주입됩니다.

 

기본적으로 Spring은 단순한 타입 변환을 지원합니다

 

Spring은 기본적으로 간단한 타입 변환을 지원합니다. 예를 들어, 쉼표로 구분된 문자열을 자동으로 문자열 배열로 변환할 수 있으며, intInteger 타입으로 자동 변환이 가능합니다. 또한, 특정 상황에서 기본적으로 제공되는 변환 외에도, 사용자 정의 변환기를 추가하여 복잡한 변환도 지원할 수 있습니다.

 

PropertySourcesPlaceholderConfigurer를 사용한 엄격한 프로퍼티 값 관리

 

기본적으로 Spring은 프로퍼티 값을 해결할 수 없을 때 @Value에 정의된 프로퍼티 이름(예: ${catalog.name})을 그대로 주입합니다. 그러나 존재하지 않는 프로퍼티 값에 대해 엄격한 관리를 하고 싶다면 PropertySourcesPlaceholderConfigurer 빈을 정의해야 합니다:

@Configuration
public class AppConfig {

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }
}

이 구성은 PropertySourcesPlaceholderConfigurer를 설정하여 프로퍼티 값이 없으면 Spring 초기화에서 오류를 발생시킵니다.

 

Spring 프레임워크는 @PostConstruct@PreDestroy 어노테이션을 사용하여 JSR-250의 라이프사이클 콜백을 지원합니다. 이 어노테이션들은 Spring 2.5에서 도입되었으며, 빈의 초기화 및 소멸 단계에서 특정 메서드를 호출할 수 있게 해줍니다. @PostConstruct는 빈이 초기화될 때 호출되며, @PreDestroy는 빈이 소멸될 때 호출됩니다.

 

예시

public class CachingMovieLister {

	@PostConstruct
	public void populateMovieCache() {
		// 초기화 시 영화 캐시를 채웁니다.
	}

	@PreDestroy
	public void clearMovieCache() {
		// 소멸 시 영화 캐시를 비웁니다.
	}
}

 

위 코드에서 populateMovieCache() 메서드는 빈이 초기화될 때 실행되고, clearMovieCache() 메서드는 빈이 소멸될 때 실행됩니다.

 

JSR-250 및 Spring 라이프사이클 콜백

 

Spring에서는 @PostConstruct@PreDestroy를 사용할 수 있는데, 이는 Spring 라이프사이클 인터페이스 메서드(InitializingBean, DisposableBean 등) 또는 명시적으로 선언된 콜백 메서드와 같은 시점에 호출됩니다.

 

이 어노테이션들은 JDK 6에서 8까지 표준 Java 라이브러리의 일부였으나, JDK 9부터는 핵심 Java 모듈에서 분리되었고, JDK 11에서는 제거되었습니다. 현재 Jakarta EE 9부터는 이 패키지가 jakarta.annotation으로 이동되었으며, 해당 라이브러리를 사용하려면 Maven Central에서 jakarta.annotation-api 아티팩트를 받아야 합니다.

 

이 어노테이션들을 사용하면 빈의 생명주기 동안 특정 작업을 자동으로 처리할 수 있어 코드의 명확성과 유지보수성을 높이는 데 도움이 됩니다.

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유