Existe uma maneira de especificar um valor de propriedade padrão em Spring XML?

91

Estamos usando um PropertyPlaceholderConfigurer para usar as propriedades java em nossa configuração Spring ( detalhes aqui )

por exemplo:

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

Gostaríamos de adicionar uma propriedade adicional, mas temos um sistema distribuído em que as instâncias existentes podem usar um valor padrão. Existe uma maneira de evitar a atualização de todos os nossos arquivos de propriedades, indicando um valor padrão na configuração do Spring para quando não há um valor de propriedade de substituição definido?

Rog
fonte

Respostas:

14

Você está procurando o PropertyOverrideConfigurer documentado aqui

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

O PropertyOverrideConfigurer, outro pós-processador de fábrica de bean, é semelhante ao PropertyPlaceholderConfigurer, mas em contraste com o último, as definições originais podem ter valores padrão ou nenhum valor para as propriedades do bean. Se um arquivo de Propriedades de substituição não tiver uma entrada para uma determinada propriedade do bean, a definição de contexto padrão é usada.

JoseK
fonte
Alguém poderia me explicar o que 18GerPD8fY4iTbNpC9hHNXNHyrDMampPLAé? Tenho certeza de que todo mundo sabe e eu sou simplesmente estúpido, mas apenas no caso ...
Sridhar Sarnobat
276

Spring 3 oferece suporte à ${my.server.port:defaultValue}sintaxe.

Lexicore
fonte
8
Apenas para a referência: SPR-4785
cubanacan
11
para mim, ele sempre substitui a propriedade com o valor padrão, não importa se a propriedade está definida ou não.
Ondrej Bozek
12
@OndrejBozek - (desculpe por esbarrar em um post antigo) Encontrei o que poderia ser o mesmo problema, consulte o problema do Spring Framework [ jira.spring.io/browse/SPR-9989] . Onde vários configuradores de espaço reservado estão envolvidos, os valores padrão especificados com a notação ':' são resolvidos apenas pelo primeiro configurador de espaço reservado na cadeia. Portanto, se o primeiro configurador não tiver a propriedade, ela sempre será definida com o valor padrão, mesmo que os configuradores mais abaixo na cadeia tenham a propriedade. Consulte [ stackoverflow.com/a/22452984/599609]
tons de
1
parece ${my.server.port:-defaultValue}também dar o mesmo resultado, observe o " :-" em oposição a " :".
Capitão Man
2
Você precisa adicionar <context:property-placeholder/>para que isso funcione ou adicionar umPropertyPlaceholderConfigurer
shuckc de
32

Existe um recurso pouco conhecido, o que torna isso ainda melhor. Você pode usar um valor padrão configurável em vez de um codificado, aqui está um exemplo:

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 o padrão e ao mesmo tempo ser capaz de substituir facilmente mais tarde, faça isso em config.properties:

timeout.myBean = ${timeout.default}
Michael Böckling
fonte
Isso funcionou para mim ${timeout.myBean:${timeout.default}}. Isso permitiu que meu padrão também fosse uma variável.
NewestStackOverflowUser
10

O valor padrão pode ser seguido por um :após a chave de propriedade, por exemplo

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

Ou em código java:

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

Vejo:

BTW, o Operador Elvis está disponível apenas em Spring Expression Language (SpEL),
por exemplo: https://stackoverflow.com/a/37706167/537554

Ryenus
fonte
8

http://thiamteck.blogspot.com/2008/04/spring-propertyplaceholderconfigurer.html aponta que as "propriedades locais" definidas no próprio bean serão consideradas padrões a serem substituídos pelos valores lidos dos arquivos:

<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
fonte
obrigado, houve palavras sobre isso no javadoc da primavera, mas eu não era capaz de descobrir como fazer isso!
Guillaume,
0

Também encontro outra solução que funciona para mim. Em nosso projeto de primavera legado, usamos este método para dar aos nossos usuários possibilidades de usar essas próprias configurações:

<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>

E em nosso código, para acessar essas propriedades, precisamos escrever algo assim:

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

E se surgir uma situação em que você precisa adicionar uma nova propriedade, mas agora você não quer adicioná-la na configuração do usuário de produção, isso se tornará um inferno quando você precisar corrigir todos os seus contextos de teste ou seu aplicativo falhará comece.

Para lidar com esse problema, você pode usar a próxima sintaxe para adicionar um valor padrão:

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

Foi uma verdadeira descoberta para mim.

Ilya
fonte