[[beans-value-annotations]]
= Using `@Value`

`@Value` is typically used to inject externalized properties:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
    @Component
    public class MovieRecommender {

        private final String catalog;

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

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Component
	class MovieRecommender(@Value("\${catalog.name}") private val catalog: String)
----
======

With the following configuration:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
    @Configuration
    @PropertySource("classpath:application.properties")
    public class AppConfig { }
----

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	@PropertySource("classpath:application.properties")
	class AppConfig
----
======

And the following `application.properties` file:

[source,java,indent=0,subs="verbatim,quotes"]
----
    catalog.name=MovieCatalog
----

In that case, the `catalog` parameter and field will be equal to the `MovieCatalog` value.

A default lenient embedded value resolver is provided by Spring. It will try to resolve the
property value and if it cannot be resolved, the property name (for example `${catalog.name}`)
will be injected as the value. If you want to maintain strict control over nonexistent
values, you should declare a `PropertySourcesPlaceholderConfigurer` bean, as the following
example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	public class AppConfig {

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

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class AppConfig {

		@Bean
		fun propertyPlaceholderConfigurer() = PropertySourcesPlaceholderConfigurer()
	}
----
======

NOTE: When configuring a `PropertySourcesPlaceholderConfigurer` using JavaConfig, the
`@Bean` method must be `static`.

Using the above configuration ensures Spring initialization failure if any `${}`
placeholder could not be resolved. It is also possible to use methods like
`setPlaceholderPrefix`, `setPlaceholderSuffix`, `setValueSeparator`, or
`setEscapeCharacter` to customize placeholders.

NOTE: Spring Boot configures by default a `PropertySourcesPlaceholderConfigurer` bean that
will get properties from `application.properties` and `application.yml` files.

Built-in converter support provided by Spring allows simple type conversion (to `Integer`
or `int` for example) to be automatically handled. Multiple comma-separated values can be
automatically converted to `String` array without extra effort.

It is possible to provide a default value as following:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
    @Component
    public class MovieRecommender {

        private final String catalog;

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

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Component
	class MovieRecommender(@Value("\${catalog.name:defaultCatalog}") private val catalog: String)
----
======

A Spring `BeanPostProcessor` uses a `ConversionService` behind the scenes to handle the
process for converting the `String` value in `@Value` to the target type. If you want to
provide conversion support for your own custom type, you can provide your own
`ConversionService` bean instance as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
    @Configuration
    public class AppConfig {

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

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Configuration
	class AppConfig {

		@Bean
		fun conversionService(): ConversionService {
			return DefaultFormattingConversionService().apply {
				addConverter(MyCustomConverter())
			}
		}
	}
----
======

When `@Value` contains a xref:core/expressions.adoc[`SpEL` expression] the value will be dynamically
computed at runtime as the following example shows:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
    @Component
    public class MovieRecommender {

        private final String catalog;

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

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Component
	class MovieRecommender(
		@Value("#{systemProperties['user.catalog'] + 'Catalog' }") private val catalog: String)
----
======

SpEL also enables the use of more complex data structures:

[tabs]
======
Java::
+
[source,java,indent=0,subs="verbatim,quotes"]
----
    @Component
    public class MovieRecommender {

        private final Map<String, Integer> countOfMoviesPerCatalog;

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

Kotlin::
+
[source,kotlin,indent=0,subs="verbatim,quotes"]
----
	@Component
	class MovieRecommender(
		@Value("#{{'Thriller': 100, 'Comedy': 300}}") private val countOfMoviesPerCatalog: Map<String, Int>)
----
======


