From 1af43d7164b885de77d55162fdb69bbaab99d32e Mon Sep 17 00:00:00 2001 From: Sebastien Deleuze Date: Tue, 11 Jun 2019 17:52:19 +0200 Subject: [PATCH] Rework @Value documentation See gh-23052 --- src/docs/asciidoc/core/core-beans.adoc | 268 ++++++++++--------------- 1 file changed, 106 insertions(+), 162 deletions(-) diff --git a/src/docs/asciidoc/core/core-beans.adoc b/src/docs/asciidoc/core/core-beans.adoc index 56094478d8..e390b5f130 100644 --- a/src/docs/asciidoc/core/core-beans.adoc +++ b/src/docs/asciidoc/core/core-beans.adoc @@ -5246,184 +5246,51 @@ 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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - private final String algorithm; - - public MovieRecommender(@Value("myRecommendationAlgorithm") String algorithm){ - this.algorithm = algorithm; - } - } ----- - -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: - - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - public class MovieRecommender { - - private final Integer depth; - - public MovieRecommender(@Value("2") Integer depth){ - this.depth = depth; - } - } ----- - -As the annotation java type does not allow non constant value such as null, you can also safely use primitive type parameter: - -[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"] ----- -public class MovieRecommender { - - private final String[] catalogs; - - 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: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- -@Configuration -public class MyConfig { - - @Bean - public static ConversionService conversionService() { - DefaultFormattingConversionService defaultFormattingConversionService = new DefaultFormattingConversionService(); - defaultFormattingConversionService.addConverter(new MyCustomConverter()); - return defaultFormattingConversionService; - } -} ----- - -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 { - - private final String catalog; - - public MovieRecommender(@Value("#{systemProperties['user.region'] + 'Catalog' }") String catalog){ - this.catalog = catalog; - } ----- - -SpEL also enables to use more complex data structure: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - -public class MovieRecommender { - - private final Map countOfMoviesPerCatalog; - - public MovieRecommender( - @Value("#{{'Thriller': 100, 'Comedy': 300}}") Map countOfMoviesPerCatalog) { - this.countOfMoviesPerCatalog = countOfMoviesPerCatalog; - } -} ----- - -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 : - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - @Configuration - @PropertySource("classpath:application.properties") - public class MyConfig { - } ----- - -And the class: +`@Value` is typically used to inject externalized properties: [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("${catalog.name}") 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: - - +With the following configuration: [source,java,indent=0] [subs="verbatim,quotes"] ---- @Configuration @PropertySource("classpath:application.properties") - public class MyConfig { + public 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 non existent +values, you should declare a `PropertySourcesPlaceholderConfigurer` bean, as the following +example shows: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Configuration + public class AppConfig { @Bean public PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() { @@ -5432,9 +5299,86 @@ as the following example shows: } ---- -Using the above configuration ensures Spring initialization failure if any of "${}" placeholder could not be resolved. +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. -NOTE: Spring Boot configures by default a `PropertySourcesPlaceholderConfigurer` bean that will get properties from `application.properties` and `application.yml` files. +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 parameter +can be automatically converted to String array without extra effort. + +It is possible to provide a default value as following: + +[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; + } + } +---- + +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 + public class AppConfig { + + @Bean + public ConversionService conversionService() { + DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(); + conversionService.addConverter(new MyCustomConverter()); + return conversionService; + } + } +---- + +<> 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; + + public MovieRecommender(@Value("#{systemProperties['user.catalog'] + 'Catalog' }") String catalog){ + this.catalog = catalog; + } + } +---- + +SpEL also enables to use more complex data structure: + +[source,java,indent=0] +[subs="verbatim,quotes"] +---- + @Component + public class MovieRecommender { + + private final Map countOfMoviesPerCatalog; + + public MovieRecommender( + @Value("#{{'Thriller': 100, 'Comedy': 300}}") Map countOfMoviesPerCatalog) { + this.countOfMoviesPerCatalog = countOfMoviesPerCatalog; + } + } +---- [[beans-postconstruct-and-predestroy-annotations]]