Spring表達式語言:SpEL(三)

本文爲轉載學習java

原文連接:http://jinnianshilongnian.iteye.com/blog/1418311spring

5.4.1  xml風格的配置


       SpEL支持在Bean定義時注入,默認使用「#{SpEL表達式}」表示,其中「#root」根對象默承認以認爲是ApplicationContext,只有ApplicationContext實現默認支持SpEL,獲取根對象屬性實際上是獲取容器中的Bean。express

       首先看下配置方式(chapter5/el1.xml)吧:安全

<bean id="world" class="java.lang.String">  
    <constructor-arg value="#{' World!'}"/>  
</bean>  
<bean id="hello1" class="java.lang.String">  
    <constructor-arg value="#{'Hello'}#{world}"/>  
</bean>    
<bean id="hello2" class="java.lang.String">  
    <constructor-arg value="#{'Hello' + world}"/>  
    <!-- 不支持嵌套的 -->  
    <!--<constructor-arg value="#{'Hello'#{world}}"/>-->  
</bean>  
<bean id="hello3" class="java.lang.String">  
    <constructor-arg value="#{'Hello' + @world}"/>  
</bean>

模板默認之前綴「#{」開頭,之後綴「}」結尾,且不容許嵌套,如「#{'Hello'#{world}}」錯誤,如「#{'Hello' + world}」中「world」默認解析爲Bean。固然可使用「@bean」引用了。ide

 

       接下來測試一下吧:post

@Test  
public void testXmlExpression() {  
    ApplicationContext ctx = new ClassPathXmlApplicationContext("chapter5/el1.xml");  
    String hello1 = ctx.getBean("hello1", String.class);  
    String hello2 = ctx.getBean("hello2", String.class);  
    String hello3 = ctx.getBean("hello3", String.class);  
    Assert.assertEquals("Hello World!", hello1);  
    Assert.assertEquals("Hello World!", hello2);  
    Assert.assertEquals("Hello World!", hello3);  
}

是否是很簡單,除了XML配置方式,Spring還提供一種註解方式@Value ,接着往下看吧。學習

 

5.4.2  註解風格的配置


       基於註解風格的SpEL配置也很是簡單,使用@Value註解來指定SpEL表達式,該註解能夠放到字段、方法及方法參數上。測試

       測試Bean類以下,使用@Value來指定SpEL表達式:spa

package cn.javass.spring.chapter5;  
import org.springframework.beans.factory.annotation.Value;  
public class SpELBean {  
    @Value("#{'Hello' + world}")  
    private String value;  
    //setter和getter因爲篇幅省略,本身寫上  
}

首先看下配置文件(chapter5/el2.xml):.net

<?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"  
        xsi:schemaLocation="  
          http://www.springframework.org/schema/beans  
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
          http://www.springframework.org/schema/context  
http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
   <context:annotation-config/>  
   <bean id="world" class="java.lang.String">  
       <constructor-arg value="#{' World!'}"/>  
   </bean>  
   <bean id="helloBean1" class="cn.javass.spring.chapter5.SpELBean"/>  
   <bean id="helloBean2" class="cn.javass.spring.chapter5.SpELBean">  
       <property name="value" value="haha"/>  
   </bean>  
</beans>

配置時必須使用「<context:annotation-config/>」來開啓對註解的支持。

 

       有了配置文件那開始測試吧:

@Test  
public void testAnnotationExpression() {  
    ApplicationContext ctx = new ClassPathXmlApplicationContext("chapter5/el2.xml");  
    SpELBean helloBean1 = ctx.getBean("helloBean1", SpELBean.class);  
    Assert.assertEquals("Hello World!", helloBean1.getValue());  
    SpELBean helloBean2 = ctx.getBean("helloBean2", SpELBean.class);  
    Assert.assertEquals("haha", helloBean2.getValue());  
}

其中「helloBean1 」值是SpEL表達式的值,而「helloBean2」是經過setter注入的值,這說明setter注入將覆蓋@Value的值。

5.4.3  在Bean定義中SpEL的問題


       若是有同窗問「#{我不是SpEL表達式}」不是SpEL表達式,而是公司內部的模板,想換個前綴和後綴該如何實現呢?

       那咱們來看下Spring如何在IoC容器內使用BeanExpressionResolver接口實現來求值SpEL表達式,那若是咱們經過某種方式獲取該接口實現,而後把前綴後綴修改了不就能夠了。

       此處咱們使用BeanFactoryPostProcessor接口提供postProcessBeanFactory回調方法,它是在IoC容器建立好但還未進行任何Bean初始化時被ApplicationContext實現調用,所以在這個階段把SpEL前綴及後綴修改掉是安全的,具體代碼以下:

package cn.javass.spring.chapter5;  
import org.springframework.beans.BeansException;  
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;  
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;  
import org.springframework.context.expression.StandardBeanExpressionResolver;  
public class SpELBeanFactoryPostProcessor implements BeanFactoryPostProcessor {  
    @Override  
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)  
        throws BeansException {  
        StandardBeanExpressionResolver resolver = (StandardBeanExpressionResolver) beanFactory.getBeanExpressionResolver();  
        resolver.setExpressionPrefix("%{");  
        resolver.setExpressionSuffix("}");  
    }  
}

首先經過 ConfigurableListableBeanFactory的getBeanExpressionResolver方法獲取BeanExpressionResolver實現,其次強制類型轉換爲StandardBeanExpressionResolver,其爲Spring默認實現,而後改掉前綴及後綴。

開始測試吧,首先準備配置文件(chapter5/el3.xml):

<?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"  
        xsi:schemaLocation="  
           http://www.springframework.org/schema/beans  
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
           http://www.springframework.org/schema/context  
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
   <context:annotation-config/>  
   <bean class="cn.javass.spring.chapter5.SpELBeanFactoryPostProcessor"/>  
   <bean id="world" class="java.lang.String">  
       <constructor-arg value="%{' World!'}"/>  
   </bean>  
   <bean id="helloBean1" class="cn.javass.spring.chapter5.SpELBean"/>  
   <bean id="helloBean2" class="cn.javass.spring.chapter5.SpELBean">  
       <property name="value" value="%{'Hello' + world}"/>  
   </bean>  
</beans>

配置文件和註解風格的幾乎同樣,只有SpEL表達式前綴變爲「%{」了,而且註冊了「cn.javass.spring.chapter5.SpELBeanFactoryPostProcessor」Bean,用於修改前綴和後綴的。

       寫測試代碼測試一下吧:

@Test  
public void testPrefixExpression() {  
    ApplicationContext ctx = new ClassPathXmlApplicationContext("chapter5/el3.xml");  
    SpELBean helloBean1 = ctx.getBean("helloBean1", SpELBean.class);  
    Assert.assertEquals("#{'Hello' + world}", helloBean1.getValue());  
    SpELBean helloBean2 = ctx.getBean("helloBean2", SpELBean.class);  
    Assert.assertEquals("Hello World!", helloBean2.getValue());  
}

此處helloBean1 中經過@Value注入的「#{'Hello' + world}」結果仍是「#{'Hello' + world}」說明不對其進行SpEL表達式求值了,而helloBean2使用「%{'Hello' + world}」注入,獲得正確的「"Hello World!」。

相關文章
相關標籤/搜索