Guía de anotación Spring @Value - Coding N Concepts

En este artículo, aprenderemos cómo inyectar valores para Primitivas, Lista, Mapa y Fecha con valores en línea y desde el archivo de propiedades usando la anotación @Value con ejemplos. También veremos su uso con inyección basada en constructor y setter, y SpEL.

La anotación @Value se usa para inyectar valores en campos en beans administrados por Spring. El valor generalmente proviene de: -

  1. Valores en línea
  2. Archivos de propiedades ((archivos .properties y .yml))
  3. Propiedades del sistema
  4. Variables de entorno
Índice
  1. Inyectar valores en línea usando @Value Annotation
  2. Inyectar valores del archivo de propiedades usando la anotación @Value
  3. Concatenar varias propiedades en la anotación @Value
  4. Inyectar con valores predeterminados usando la anotación @Value
  5. Inyectar lista usando la anotación @Value
  6. Inyectar mapa usando la anotación @Value
  7. Inyectar fecha usando la anotación @Value
  8. Inyectar propiedades del sistema usando la anotación @Value
  9. Inyección basada en constructor usando la anotación @Value
  10. Inyección basada en setter usando la anotación @Value
  11. Inyectar argumentos de método usando la anotación @Value
  12. SpEL (SpEL Expression Language) con anotación @Value
  13. Resumen

Inyectar valores en línea usando @Value Annotation

Veamos los ejemplos rápidos para aprender cómo inyectar valores en línea para String, Integer, Float, Double, Booleany List utilizando @Value anotación. Inyectar valores en línea para Map, Date, LocalDate, LocalDateTime requiere SpEL (SpEL Expression Language) para usar dentro @Value anotación.

@Configuration
public class InlineConfig {

    @Value("How to use @Value Annotation with inline values")
    private String title;

    @Value("30")
    private Integer duration;

    @Value("4.5")
    private Float rating;

    @Value("1e+10")
    private Double pageViews;

    @Value("true")
    private Boolean isTrending;

    @Value("Spring, Spring Boot, Annotation")
    private List<String> tags;

    // SpEL expression used to initialize a Map
    @Value("#{{'keyword1': '12', 'keyword2': '44', 'keyword3': '85', 'keyword4': '100'}}")
    private Map<String, Integer> keywordCountMap;

    // Inject Date with given format using SpEL expression
    @Value("#{new java.text.SimpleDateFormat('yyyyMMdd').parse('20210530')}")
    private Date createdDate;

    // Inject LocalDate with ISO_DATE format using SpEL expression
    @Value("#{T(java.time.LocalDate).parse('2021-05-31')}")
    private LocalDate updatedDate;

    // Inject LocalDateTime with ISO_LOCAL_DATE_TIME format using SpEL expression
    @Value("#{T(java.time.LocalDateTime).parse('2015-08-04T10:11:30')}")
    private LocalDateTime lastAccess;
}

Inyectar valores del archivo de propiedades usando la anotación @Value

application.properties

course.title = "How to use Spring @Value annotation" course.duration = 30 course.rating = 4.5 course.page_views = 1e+10 course.trending = true

Podemos establecer los valores de campos primitivos como cadena de caracteres, entero, flotar, doble y booleano del archivo de propiedad como se muestra a continuación: -

@Configuration
public class CourseConfig {

	@Value("${course.title}")
	private String title;
	//How to use Spring @Value annotation
	
	@Value("${course.duration}")
	private int duration;
	//30
	
	@Value("${course.rating}")
	private float rating;
	//4.5
	
	@Value("${course.page_views}")
	private double pageViews;
	//1.0E10
	
	@Value("${course.trending}")
	private boolean isTrending;
	//true
}

Concatenar varias propiedades en la anotación @Value

Se pueden concatenar dos o más propiedades desde el archivo de propiedades como se muestra a continuación:

@Configuration
public class CourseConfig {

  @Value("${course.title} (${course.rating})")
  private String titleAndRating;
  //How to use Spring @Value annotation (4.5)

  @Value("${course.title} - ${course.duration} min")
  private String titleAndDuration;
  //How to use Spring @Value annotation - 30 min
}

Inyectar con valores predeterminados usando la anotación @Value

Se pueden proporcionar valores predeterminados para propiedades que podrían no establecerse utilizando la siguiente sintaxis:

@Value("${property: defaultValue}")

Por ejemplo, la propiedad course.review por lo tanto no está definido revisión el campo se inicializará con el valor predeterminado, es decir, "Sin comentarios todavía".

@Value("${course.review: No Reviews Yet}")
private String review;

Inyectar lista usando la anotación @Value

aplicación.propiedades

application.properties

course.tags = Java, Spring, Spring Boot, Annotation

Cualquier propiedad que tenga los valores separados por comas se pueden inicializar como una lista utilizando @Value anotación en la última versión de Spring.

// Comma separated property values auto initialize a List
@Value("${course.tags}")
private List<String> tags;

Uso de expresión SpEL con lista

Si está utilizando una versión anterior de Spring, debe usar HECHIZO expresión para inicializar un Lista:

@Value("#{'${course.tags}'.split(',')}")
private List<String> tags;

HECHIZO La expresión también se puede usar para obtener un valor específico de valores separados por comas:

@Value("#{'${course.tags}'.split(',')[0]}")
private String firstTag;

Inyectar mapa usando la anotación @Value

application.properties

course.keyword_count = { 'keyword1': '12', 'keyword2': '44', 'keyword3': '85', 'keyword4': '100'}

Nota*: Las claves y los valores de las propiedades del mapa deben estar entre comillas simples ' '.

Puede inicializar un Mapa con la propiedad anterior usando HECHIZO expresión dentro @Value anotación

// SpEL expression used to initialize a Map
@Value("#{${course.keyword_count}}")
private Map<String, Integer> keywordCountMap;

Inyectar el valor de una clave específica del mapa

Si necesitamos obtener el valor de una clave específica de Mapatodo lo que tenemos que hacer es agregar el nombre de la clave en la expresión:
Podemos usar cualquiera de estas dos formas: -

// way 1 - .key
@Value("#{${course.keyword_count}.keyword1}")
private Integer FirstKeywordCount;

// way 2 - ['key']
@Value("#{${course.keyword_count}['keyword2']}")
private Integer SecondKeywordCount;

Si no estamos seguros de que el Mapa contiene una determinada clave, debemos elegir una expresión más segura que no generará una excepción pero establecerá el valor en malo cuando no se encuentra la clave:

@Value("#{${course.keyword_count}['unknownKey']}")
private Integer unknownKeywordCount;

Inyectar mapa con predeterminado

nosotros también podemos establecer valores predeterminados para propiedades o claves que podrían no existir:

@Value("#{${unknownMap : {key1: '1', key2: '2'}}}")
private Map<String, Integer> unknownMap;
	
@Value("#{${course.keyword_count}['unknownKey'] ?: 100}")
private Integer unknownKeyWithDefaultValue;

Inyectar entradas de mapas filtrados

Las entradas de tarjeta también se pueden filtrar antes de la inyección. Supongamos que necesitamos obtener solo entradas con un recuento de palabras clave superior a 50:

@Value("#{${course.keyword_count}.?[value > '50']}")
private Map<String, Integer> keywordCountMapFiltered;

Inyectar fecha usando la anotación @Value

application.properties

course.created_date = 20210530 course.updated_date = 2021-05-31 course.last_access = 2015-08-04T10:11:30

No hay soporte directo para inicializar Date, LocalDatey LocalDateTime campos usando @Value anotación. Necesitamos usar SpEL (Lenguaje de Expresión Spring) dentro @Value anotación para analizar la propiedad en función de la cadena.

// Inject Date with given format using SpEL expression
@Value("#{new java.text.SimpleDateFormat('yyyyMMdd').parse('${course.created_date}')}")
private Date createdDate;

// Inject LocalDate with ISO_DATE format using SpEL expression
@Value("#{T(java.time.LocalDate).parse('${course.updated_date}')}")
private LocalDate updatedDate;

// Inject LocalDateTime with ISO_LOCAL_DATE_TIME format using SpEL expression
@Value("#{T(java.time.LocalDateTime).parse('${course.last_access}')}")
private LocalDateTime lastAccess;

Inyectar propiedades del sistema usando la anotación @Value

Podemos inicializar campos desde las propiedades del sistema usando @Value anotación de la misma manera que se definieron en un archivo de propiedades. Veamos ejemplos:-

//UTF-8
@Value("${file.encoding}")
private String fileEncoding;

//Mac OS X
@Value("${os.name}")
private String osName;

// /Users/ashishkumarlahoti
@Value("${user.home}")
private String userHome

Inyectar todas las propiedades del sistema

También podemos usar el @Value anotación para inyectar todas las propiedades actuales del sistema como esta: -

@Value("#{systemProperties}")
private Map<String, String> systemPropertiesMap;

Output

systemPropertiesMap: { "os.name" : "Mac OS X", "os.version" : "10.15.7", "user.name" : "ashl", "user.country" : "SG", "user.language" : "en", "user.timezone" : "Asia/Singapore", "user.home" : "/Users/ashl", "user.dir" : "/Users/ashl/IdeaProjects/springboot-examples/springboot-demo", "file.encoding" : "UTF-8", "file.separator" : "/", "line.separator" : "n", "path.separator" : ":", "java.version" : "11.0.10", "java.vendor" : "Oracle Corporation", "java.home" : "/Library/Java/JavaVirtualMachines/jdk-11.0.10.jdk/Contents/Home", "catalina.home" : "/private/var/folders/6p/3ztts6bd4xbdl7nkcq6lpcg80000gn/T/tomcat.8080.8199922893426879147" }

Inyectar el valor de la propiedad específica del sistema desde el Mapa

También podemos usar HECHIZO expresiones a obtenga el valor del mapa de propiedades del sistema:

// /Library/Java/JavaVirtualMachines/jdk1.8.0_211.jdk/Contents/Home/jre
@Value("#{systemProperties['java.home']}")
private String javaHome;

//Oracle Corporation
@Value("#{systemProperties['java.vendor']}")
private String javaVendor;

Inyectar propiedad del sistema con valor predeterminado

También podemos inicializar un valor predeterminado si la propiedad System no está disponible:

@Value("#{systemProperties['unknown'] ?: 'Default Value'}")
private String unknownSystemProperty;

Inyección basada en constructor usando la anotación @Value

Cuando usamos el @Value anotación, no estamos limitados a la inyección basada en campo. Podemos usar el @Value anotación para inyección basada en constructor también.

Veamos esto en la práctica:

values.properties

priority = high
@Component
@PropertySource("classpath:values.properties")
public class PriorityProvider {
 
    private String priority;
 
    @Autowired
    public PriorityProvider(@Value("${priority:normal}") String priority) {
        this.priority = priority;
    }
}

En el ejemplo anterior, estamos inyectando una propiedad priority directamente en el constructor PriorityProvider. Tenga en cuenta que también proporcionamos un valor predeterminado "normal" por si acaso priority la propiedad no se puede encontrar.

Inyección basada en setter usando la anotación @Value

Similar a la inyección basada en campo y en constructor, también podemos usar @Value anotación para inyección basada en setter.

values.properties

listOfValues = first, second, third
@Component
@PropertySource("classpath:values.properties")
public class CollectionProvider {
 
    private List<String> values = new ArrayList<>();
 
    @Autowired
    public void setValues(@Value("#{'${listOfValues}'.split(',')}") List<String> values) {
        this.values.addAll(values);
    }
}

En el código anterior, usamos la expresión SpEL para inyectar una lista de valores en el método setValues.

Inyectar argumentos de método usando la anotación @Value

Cuando el @Value Se encuentra una anotación en un método, el contexto de Spring la invocará cuando se carguen todas las configuraciones y beans de Spring. Si el método tiene varios argumentos, cada valor de argumento se asigna a partir de la anotación del método. Si queremos diferentes valores para diferentes argumentos, podemos usar @Value anotación directamente con el argumento.

@Configuration
public class Config {

    @Value("Test")
    public void printValues(String a, String b){
      System.out.println(a + " & " + b); // Test & Test
    }

    @Value("Test")
    public void printOtherValues(String a, @Value("Another Test") String b){
      System.out.println(a + " & " + b); // Test & Another Test
    }
}

SpEL (SpEL Expression Language) con anotación @Value

Ya hemos visto el uso de SpEL con @Value anotación para inyectar valores complejos como Lista, Mapa y Fecha donde Spring boot no proporciona soporte directo. SpEL nos da la flexibilidad de transformar o analizar el valor de la propiedad antes de la inyección. Veamos algunos casos de uso más prácticos: -

Inyectar esquema, host o puerto desde URL

application.properties

bootstrap.url = http://localhost:8080
 @Value("#{new java.net.URI('${bootstrap.url}').getScheme()}")
private String scheme; //http

@Value("#{new java.net.URI('${bootstrap.url}').getHost()}")
private String host;  //localhost

@Value("#{new java.net.URI('${bootstrap.url}').getPort()}")
private Integer port; //8080

Operaciones aritmeticas
@Value("#{((1 + 2^3 - 4) * (5 % 6)) / 7 }") // 3.0
private Double arithmeticOperation;

@Value("#{((1 + 2^3 - 4) * (5 mod 6)) div 7 }") // 3.0
private Double anotherArithmeticOperation;

@Value("#{'Hello ' + 'World'}") // "Hello World"
private String concatString;

Podemos usar cualquiera -
div Donde para la operación DIVIDE,
mod Donde % para funcionamiento MÓDULO.

los + El operador también se puede utilizar para concatenar cadenas.

operaciones relacionales
// @Value("#{1 == 1}") true
@Value("#{1 eq 1}") // true
private boolean equal;

//@Value("#{1 != 1}") // false
@Value("#{1 ne 1}") // false
private boolean notEqual;

// @Value("#{1 < 1}") // false
@Value("#{1 lt 1}") // false
private boolean lessThan;

//@Value("#{1 <= 1}") // true
@Value("#{1 le 1}") // true
private boolean lessThanOrEqual;

//@Value("#{1 > 1}") // false
@Value("#{1 gt 1}") // false
private boolean greaterThan;

//@Value("#{1 >= 1}") // true
@Value("#{1 ge 1}") // true
private boolean greaterThanOrEqual;

Podemos usar cualquiera -
eq Donde == para operación IGUAL,
!= Donde ne para operación NO IGUAL,
< Donde lt para operación BAJO,
> Donde gt para una operación MAYOR QUE,
<= Donde le para la operación MENOS QUE IGUAL,
>= Donde ge para una operación MAYOR QUE IGUAL

Operaciones lógicas
//@Value("#{250 > 200 && 200 < 4000}") // true
@Value("#{250 > 200 and 200 < 4000}") // true
private boolean andOperation; 

//@Value("#{400 > 300 || 150 < 100}") // true
@Value("#{400 > 300 or 150 < 100}") // true
private boolean orOperation;

//@Value("#{!true}") // false
@Value("#{not true}") // false
private boolean notOperation;

Podemos usar cualquiera -
&& Donde and para la operación AND,
|| Donde or para una operación OR,
! Donde not para NO operar.

Operaciones condicionales

El operador ternario se puede usar dentro de la expresión para la lógica condicional.

@Value("#{2 > 1 ? 'a' : 'b'}") // "a"
private String ternaryOperator;

El caso de uso más común del operador ternario es verificar nulo y devolver el valor predeterminado.

@Autowired
private SomeBean someBean;

@Value("#{someBean.someProperty != null ? someBean.someProperty : 'default'}")
private String nullCheckUsingTernaryOperator;

SpEL también proporciona soporte para Elvis operador ?: que es una abreviatura del operador ternario para verificación nula. El ejemplo anterior se puede escribir usando el operador Elvis de esta manera:

@Value("#{someBean.someProperty ?: 'default'}") // Will inject provided string if someProperty is null
private String nullCheckUsingElvisOperator;

Resumen

Aprendimos diferentes formas de inyectar valores usando Spring @Value anotación. También entendimos el poder y la flexibilidad que brinda SpEL para usar expresiones dentro @Value anotación.

Descargue el código fuente para todos los ejemplos de github/springboot-config

Si quieres conocer otros artículos parecidos a Guía de anotación Spring @Value - Coding N Concepts puedes visitar la categoría Tutoriales.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Subir

Esta página web utiliza cookies para analizar de forma anónima y estadística el uso que haces de la web, mejorar los contenidos y tu experiencia de navegación. Para más información accede a la Política de Cookies . Ver mas