Как язык выражения Spring 3 взаимодействует с заполнителями свойств? - программирование
Подтвердить что ты не робот

Как язык выражения Spring 3 взаимодействует с заполнителями свойств?

Spring 3 представил новый язык выражений (SpEL), который может использоваться в определениях bean. Сам синтаксис достаточно хорошо определен.

Не ясно, как, если вообще, SpEL взаимодействует с синтаксисом заполнителя свойства, который уже присутствовал в предыдущих версиях. Имеет ли SpEL поддержку заполнителей свойств, или мне нужно объединить синтаксис обоих механизмов и надеяться, что они объединятся?

Позвольте мне привести конкретный пример. Я хочу использовать синтаксис свойства ${x.y.z}, но с добавлением синтаксиса "по умолчанию", предоставленного оператором elis для обработки случаев, когда ${x.y.z} - undefined.

Я пробовал следующие синтаксисы без успеха:

  • #{x.y.z?:'defaultValue'}
  • #{${x.y.z}?:'defaultValue'}

Первый дает мне

Поле или свойство 'x' не могут быть найдены на объект типа 'Org.springframework.beans.factory.config.BeanExpressionContext'

который предполагает, что SpEL не признает это как заполнитель свойств.

Второй синтаксис выдает исключение, говорящее, что местозаполнитель не распознается, поэтому вызывающий объект-заполнитель вызывается, но не работает должным образом, поскольку свойство не определено.

В документах не упоминается об этом взаимодействии, поэтому либо такая вещь невозможна, либо недокументирована.

Кому это удалось?


Хорошо, я придумал небольшой, автономный тестовый пример. Это все работает как есть:

Сначала определения bean:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:util="http://www.springframework.org/schema/util"
           xsi:schemaLocation="
                http://www.springframework.org/schema/beans   http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                http://www.springframework.org/schema/util    http://www.springframework.org/schema/util/spring-util.xsd
           "> 

    <context:property-placeholder properties-ref="myProps"/>

    <util:properties id="myProps">
        <prop key="x.y.z">Value A</prop>
    </util:properties>

    <bean id="testBean" class="test.Bean">
            <!-- here is where the magic is required -->
        <property name="value" value="${x.y.z}"/> 

            <!-- I want something like this
        <property name="value" value="${a.b.c}?:'Value B'"/> 
            --> 
    </bean>     
</beans>

Тогда тривиальный класс bean:

пакетный тест;

public class Bean {

    String value;

    public void setValue(String value) {
        this.value = value;
    }
}

И, наконец, тестовый пример:

package test;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class PlaceholderTest {

    private @Resource Bean testBean;

    @Test
    public void valueCheck() {
        assertThat(testBean.value, is("Value A"));
    }
}

Задача - придумать выражение SpEL в файле beans, которое позволяет мне указать значение по умолчанию в случаях, когда ${x.y.z} не может быть разрешено, и это значение по умолчанию должно быть указано как часть выражения, а не экстернализируется в другом наборе свойств.

4b9b3361

Ответ 1

Чтобы получить доступ к заполнителю свойств из выражения SpEL, можно использовать следующий синтаксис: #{'${x.y.z}'}. Hovewer, он не может решить вашу проблему с помощью оператора elvis и значений по умолчанию, потому что он генерирует исключение, если ${x.y.z} не может быть разрешено.

Но вам не нужно, чтобы SpEL объявлял значения по умолчанию для свойств:

<context:property-placeholder location="..." properties-ref="defaultValues"/>

<bean id = "defaultValues" class = "org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="properties">
        <props>
            <prop key="x.y.z">ZZZ</prop>
        </props>
    </property>
</bean>

<bean ...>
    <property name = "..." value = "${x.y.z}" />
</bean>

Ответ 2

Кажется, вы пропустили двоеточие:

#{ ${x.y.z} ?: 'defaultValue' }

Ответ 3

Если вы просто хотите установить значение по умолчанию для заполнителя, см. this:

   <property name="value" value="${x.y.z:defaultValue}"/> 

Если вы хотите протестировать взаимодействие между SpEL и placeholder, используя это:

   <!-- set value "77-AA-BB-CC-88" when property "x.y.z" not exist -->
   <property name="value" value="77-#{'AA-${x.y.z:BB}-CC'}-88"/>

Ответ 4

${myProps.item:defaultValue} означает, что, когда myProps.item не существует, используйте defaultValue. Это поведение по умолчанию заполнитель свойств.

#{defaultValue} означает значение SpEL для буквенного значения.

Итак, ${myProps.item:#{defaultValue}} означает, что myProps.item не существует, затем вычисляет значение SpEL и назначает его целевому полю.

Пример:

${redis.auth:#{null}} означает, что когда свойства redis.auth не существуют, установите его на null.

Ответ 5

Фактически Property-Placeholder может самостоятельно решить ваши проблемы. То есть вы можете явно указать параметры по умолчанию в контексте Spring, используя свойство properties. Затем вы можете указать местоположение для параметров, которые должны использоваться, и установить свойство localOverride на true. В этом случае все свойства, которые будут найдены во внешних ресурсах (указанные в свойстве location), переопределяют значения по умолчанию (явно определенные в контексте).

Надеюсь, я помог.

Ответ 6

Вам нужно добавить это, чтобы запустить его в вашем примере

<bean id="testBean" class="elvis.Bean">
        <!-- here is where the magic is required
    <property name="value" value="${x.y.z}"/>
    -->

        <!-- I want something like this -->
    <property name="value" value="#{myProps.get('a.b.c')?:'Value B'}"/>

</bean>

Ваш подход не работает, потому что Spring пытается оценить ${a.b.c} объект a с членом b с элементом c, который приводит к NPE, потому что a не существует.

Ответ 7

вы можете:

<bean id="testBean" class="test.Bean">
        <!-- if 'a.b.c' not found, then value="Value B" --->
       <property name="value" value="${a.b.c:Value B}"/> 
</bean>     

или

 ...
 <!-- if 'a.b.c' not found , but 'a.b' found ,then value=${a.b}
      if 'a.b' also not found , then value="a"     
 -->
 <property name="value" value="${a.b.c:${a.b:a}"/> 
 ...

или      ...

   <!-- if 'a.b.c' not found , but 'a.b' found ,then value=${a.b}
      if 'a.b' also not found , then value="a"     
    -->
       <property name="value" value="#{  '${a.b.c:}'  ?: '${a.b:a}' }"/> 
   ...

Ответ 8

Я пробовал следующее, и это сработало (довольно уродливо):

#{ myProps.getProperty('x.y.z')?:'Value B' }