본문 바로가기

SpringFramework Core - I. IoC 컨테이너/9. 어노테이션 기반의 컨테이너 설정

9.8. @Value 사용하기

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

 

 

@Value는 전형적으로 외부의 프로퍼티들을 주입할 때 사용된다.

@Component
public class MovieRecommender {

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

다음 설정과 함께 사용된다.

@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig {  }

다음은 application.properties 파일이다.

catalog.name=MovieCatalog

이 경우에, catalog 매개변수와 필드는 'MovieCatalog'라는 값과 같게 된다.

 

관대한 기본 내장 value resolver는 스프링에 의해 제공된다. 이 분석기는 프로퍼티 값의 분석을 시도하고, 만약 분석되지 않으면 프로퍼티의 이름을 값으로 주입시킨다(예를들어 ${catalog.name}). 만약 존재하지 않는 값에 대하여 엄격한 제어를 원한다면 PropertySourcesPlaceholderConfigurer bean을 선언해야 한다. 다음 예시를 보자.

@Configuration
public class AppConfig {

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

※ JavaConfig를 사용하는 PropertySourcesPlaceholderConfigurer를 설정할때, @Bean 메소드는 반드시 static이어야 한다.

 

위 설정을 사용하면 ${} placeholder가 하나라도 분석되지 않을 때, 스프링 초기화가 실패한다. placeholder들을 커스터마이징하기 위해 setPlaceholderPrefix, setPlaceholderSuffix, setValueSeparator와 같은 메소드들을 활용하는 것도 가능하다.

 

※ 스프링부트는 기본적으로 application.properties와 application.yml 파일들에서 프로퍼티들을 가져오는 PropertySourcesPlaceholderConfigurer bean을 설정한다.

 

스프링에 의해 제공되는 내장된 변환기는 기본 타입의 변환이 자동적으로 이루어지게 한다(Integer나 int 등). 콤마(,)로 구분된 복수의 값들은 자동적으로 문자 배열로 변환된다. 

 

다음과 같이 기본 값을 제공하는 것이 가능하다.

@Component
public class MovieRecommender {

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

스프링의 BeanPostProcessor는 @Value 안의 문자열 값들을 대상 타입을 변환시켜주기 위해 보이지 않는 곳에서 ConversionService를 사용한다. 만약 여러분의 커스텀한 타입을 위한 변환을 지원하고 싶다면 다음 예시처럼 여러분만의 ConversionService bean 인스턴스를 제공하면 된다.

@Configuration
public class AppConfig {

    @Bean
    public ConversionService conversionService() {
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
        conversionService.addConverter(new MyCustomConverter());
        return conversionService;
    }
}

@Value가 SpEL 표현식을 포함하고 있을 때는, 값이 런타임 시에 동적으로 계산된다. 다음 예시를 보자. 

@Component
public class MovieRecommender {

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

SpEL은 더 복잡한 자료 구조들도 사용할 수 있게 해준다.

@Component
public class MovieRecommender {

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