¿Hay alguna forma de especificar un valor de propiedad predeterminado en Spring XML?

91

Estamos usando un PropertyPlaceholderConfigurer para usar propiedades java en nuestra configuración de Spring ( detalles aquí )

p.ej:

<foo name="port">
  <value>${my.server.port}</value>
</foo>

Nos gustaría agregar una propiedad adicional, pero tenemos un sistema distribuido donde las instancias existentes podrían usar un valor predeterminado. ¿Hay alguna forma de evitar actualizar todos nuestros archivos de propiedades, indicando un valor predeterminado en la configuración de Spring para cuando no hay un valor de propiedad primordial definido?

Rog
fuente

Respuestas:

14

¿Está buscando el PropertyOverrideConfigurer documentado aquí?

http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-overrideconfigurer

PropertyOverrideConfigurer, otro postprocesador de la fábrica de frijoles, es similar al PropertyPlaceholderConfigurer, pero a diferencia de este último, las definiciones originales pueden tener valores predeterminados o ningún valor para las propiedades de los frijoles. Si un archivo de propiedades primordial no tiene una entrada para una determinada propiedad de bean, se utiliza la definición de contexto predeterminada.

JoseK
fuente
¿Alguien podría explicarme qué 18GerPD8fY4iTbNpC9hHNXNHyrDMampPLAes? Estoy seguro de que todos los demás lo saben y soy estúpido, pero por si acaso ...
Sridhar Sarnobat
276

Spring 3 admite la ${my.server.port:defaultValue}sintaxis.

lexicore
fuente
8
Solo como referencia: SPR-4785
cubanacan
11
para mí, siempre anula la propiedad con el valor predeterminado sin importar si la propiedad está definida o no.
Ondrej Bozek
12
@OndrejBozek - (lamento encontrar una publicación antigua) Me he encontrado con lo que podría ser el mismo problema, consulte el problema de Spring Framework [ jira.spring.io/browse/SPR-9989] . Cuando hay varios configuradores de marcador de posición involucrados, los valores predeterminados especificados con la notación ':' solo se resuelven mediante el primer configurador de marcador de posición de la cadena. Entonces, si el primer configurador no tiene la propiedad, la propiedad siempre se establecerá en el valor predeterminado, incluso si los configuradores más abajo de la cadena sí tienen la propiedad. Ver [ stackoverflow.com/a/22452984/599609]
tonos del
1
parece que ${my.server.port:-defaultValue}también da el mismo resultado, tenga en cuenta el " :-" en lugar de " :".
Captain Man
2
Necesita agregar <context:property-placeholder/>para que esto funcione, o agregar unPropertyPlaceholderConfigurer
shuckc
32

Hay una característica poco conocida que lo hace aún mejor. Puede utilizar un valor predeterminado configurable en lugar de uno codificado, aquí hay un ejemplo:

config.properties:

timeout.default=30
timeout.myBean=60

context.xml:

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location">
        <value>config.properties</value>
    </property>
</bean>

<bean id="myBean" class="Test">
    <property name="timeout" value="${timeout.myBean:${timeout.default}}" />
</bean>

Para usar el valor predeterminado y poder anular fácilmente más adelante, haga esto en config.properties:

timeout.myBean = ${timeout.default}
Michael Böckling
fuente
Esto funcionó para mí ${timeout.myBean:${timeout.default}}. Esto permitió que mi valor predeterminado también fuera una variable.
NewestStackOverflowUser
11

El valor predeterminado se puede seguir con una :después de la clave de propiedad, p. Ej.

<property name="port" value="${my.server.port:8080}" />

O en código java:

@Value("${my.server.port:8080}")
private String myServerPort;

Ver:

Por cierto, Elvis Operator solo está disponible en Spring Expression Language (SpEL),
por ejemplo: https://stackoverflow.com/a/37706167/537554

ryenus
fuente
8

http://thiamteck.blogspot.com/2008/04/spring-propertyplaceholderconfigurer.html señala que las "propiedades locales" definidas en el propio bean se considerarán valores predeterminados que se anularán con los valores leídos de los archivos:

<bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  <property name="location"><value>my_config.properties</value></property>  
  <property name="properties">  
    <props>  
      <prop key="entry.1">123</prop>  
    </props>  
  </property>  
</bean> 
Robert Tupelo-Schneck
fuente
Gracias, hubo palabras sobre eso en Spring Javadoc, ¡pero no pude imaginar cómo hacerlo!
Guillaume
0

También encuentro otra solución que me funciona. En nuestro proyecto de primavera heredado usamos este método para brindar a nuestros usuarios la posibilidad de usar estas propias configuraciones:

<bean id="appUserProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="ignoreResourceNotFound" value="false"/>
    <property name="locations">
        <list>
            <value>file:./conf/user.properties</value>
        </list>
    </property>
</bean>

Y en nuestro código para acceder a estas propiedades necesitamos escribir algo como eso:

@Value("#{appUserProperties.userProperty}")
private String userProperty

Y si surge una situación en la que necesita agregar una nueva propiedad, pero en este momento no desea agregarla en la configuración del usuario de producción, se convierte muy rápidamente en un infierno cuando necesita parchear todos sus contextos de prueba o su aplicación fallará. puesta en marcha.

Para manejar este problema, puede usar la siguiente sintaxis para agregar un valor predeterminado:

@Value("#{appUserProperties.get('userProperty')?:'default value'}")
private String userProperty

Fue un verdadero descubrimiento para mí.

Ilya
fuente