Browse Source

Rework @Value documentation

See gh-23052
pull/23119/head
Sebastien Deleuze 7 years ago
parent
commit
1af43d7164
  1. 182
      src/docs/asciidoc/core/core-beans.adoc

182
src/docs/asciidoc/core/core-beans.adoc

@ -5246,196 +5246,140 @@ named "customerPreferenceDao" and then falls back to a primary type match for th @@ -5246,196 +5246,140 @@ named "customerPreferenceDao" and then falls back to a primary type match for th
[[beans-value-annotations]]
=== Using `@Value`
You can use `@Value` annotation to inject a default value to a constructor parameter, as the following example shows:
`@Value` is typically used to inject externalized properties:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Component
public class MovieRecommender {
private final String algorithm;
private final String catalog;
public MovieRecommender(@Value("myRecommendationAlgorithm") String algorithm){
this.algorithm = algorithm;
public MovieRecommender(@Value("${catalog.name}") String catalog) {
this.catalog = catalog;
}
}
----
You can also apply the `@Value` annotation to fields, as the following example shows:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
public class MovieRecommender {
@Value("myAlgorithm")
private String algorithm;
}
----
Built-in converter support provided by Spring allows simple type conversion to be automatically handled, as the following example shows:
With the following configuration:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
public class MovieRecommender {
private final Integer depth;
public MovieRecommender(@Value("2") Integer depth){
this.depth = depth;
}
}
@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig { }
----
As the annotation java type does not allow non constant value such as null, you can also safely use primitive type parameter:
And the following `application.properties` file:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
public class MovieRecommender {
private final int depth;
public MovieRecommender(@Value("2") int depth){
this.depth = depth;
}
}
----
Multiple comma separated values parameter can be automatically converted to String array without extra effort:
[source,java,indent=0]
[subs="verbatim,quotes"]
catalog.name=MovieCatalog
----
public class MovieRecommender {
private final String[] catalogs;
In that case, the `catalog` parameter and field will be equal to the `MovieCatalog` value.
public MovieRecommender(@Value("catalogA,catalogB") String[] catalogs){
this.catalogs = catalogs;
}
}
----
Spring BeanPostProcessor uses ConversionService instance behind the scene to handle the process from converting
`@Value` 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:
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 non existent
values, you should declare a `PropertySourcesPlaceholderConfigurer` bean, as the following
example shows:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Configuration
public class MyConfig {
@Configuration
public class AppConfig {
@Bean
public static ConversionService conversionService() {
DefaultFormattingConversionService defaultFormattingConversionService = new DefaultFormattingConversionService();
defaultFormattingConversionService.addConverter(new MyCustomConverter());
return defaultFormattingConversionService;
@Bean
public PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
}
----
SpEL built-in support allows dynamically computed `@Value` at runtime as in the following example shows:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
public class MovieRecommender {
Using the above configuration ensures Spring initialization failure if any of `${}`
placeholder could not be resolved. It is also possible to use methods like
`setPlaceholderPrefix`, `setPlaceholderSuffix` or `setValueSeparator` to customize placeholders.
private final String catalog;
NOTE: Spring Boot configures by default a `PropertySourcesPlaceholderConfigurer` bean that
will get properties from `application.properties` and `application.yml` files.
public MovieRecommender(@Value("#{systemProperties['user.region'] + 'Catalog' }") String catalog){
this.catalog = catalog;
}
----
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 parameter
can be automatically converted to String array without extra effort.
SpEL also enables to use more complex data structure:
It is possible to provide a default value as following:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Component
public class MovieRecommender {
public class MovieRecommender {
private final Map<String, Integer> countOfMoviesPerCatalog;
private final String catalog;
public MovieRecommender(
@Value("#{{'Thriller': 100, 'Comedy': 300}}") Map<String, Integer> countOfMoviesPerCatalog) {
this.countOfMoviesPerCatalog = countOfMoviesPerCatalog;
public MovieRecommender(@Value("${catalog.name:defaultCatalog}") String catalog) {
this.catalog = catalog;
}
}
}
----
A widely spread use of `@Value` is placeholder substitution from `@PropertySource`.
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 will be injected as the value. For instance, according to the following application.properties content:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
catalogName=MovieCatalog
----
The following configuration :
Spring BeanPostProcessor uses ConversionService instance behind the scene to handle the
process from converting `@Value` 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:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Configuration
@PropertySource("classpath:application.properties")
public class MyConfig {
public class AppConfig {
@Bean
public ConversionService conversionService() {
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
conversionService.addConverter(new MyCustomConverter());
return conversionService;
}
}
----
And the class:
<<expressions, `SpEL` expression>> built-in support allows dynamically computed `@Value`
at runtime as in the following example shows:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Component
public class MovieRecommender {
private final String catalog;
private final String region;
public MovieRecommender(
@Value("${catalogName}") String catalog, @Value("${region}") String region) {
public MovieRecommender(@Value("#{systemProperties['user.catalog'] + 'Catalog' }") String catalog){
this.catalog = catalog;
this.region = region;
}
}
----
The `catalog` attribute will be equal to the `"MovieCatalog"` value.
The region attribute will be equal the `"${region}"` value.
If you want to maintain strict control over non existent values, you should declare a `PropertySourcesPlaceholderConfigurer` bean,
as the following example shows:
SpEL also enables to use more complex data structure:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
@Configuration
@PropertySource("classpath:application.properties")
public class MyConfig {
@Component
public class MovieRecommender {
@Bean
public PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
private final Map<String, Integer> countOfMoviesPerCatalog;
public MovieRecommender(
@Value("#{{'Thriller': 100, 'Comedy': 300}}") Map<String, Integer> countOfMoviesPerCatalog) {
this.countOfMoviesPerCatalog = countOfMoviesPerCatalog;
}
}
----
Using the above configuration ensures Spring initialization failure if any of "${}" placeholder could not be resolved.
NOTE: Spring Boot configures by default a `PropertySourcesPlaceholderConfigurer` bean that will get properties from `application.properties` and `application.yml` files.
[[beans-postconstruct-and-predestroy-annotations]]
=== Using `@PostConstruct` and `@PreDestroy`

Loading…
Cancel
Save