5.4.1  xml风格的配置

       SpEL支持在Bean定义时注入,默认使用“#{SpEL表达式}”表示,其中“#root”根对象默认可以认为是ApplicationContext,只有ApplicationContext实现默认支持SpEL,获取根对象属性其实是获取容器中的Bean。

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

 



java代码:

查看 复制到剪贴板 打印


1. <bean id="world" class="java.lang.String">  
2. "#{' World!'}"/>  
3. </bean>  
4. <bean id="hello1" class="java.lang.String">  
5. "#{'Hello'}#{world}"/>  
6. </bean>    
7. <bean id="hello2" class="java.lang.String">  
8. "#{'Hello' + world}"/>  
9.     <!-- 不支持嵌套的 -->  
10. "#{'Hello'#{world}}"/>-->  
11. </bean>  
12. <bean id="hello3" class="java.lang.String">  
13. "#{'Hello' + @world}"/>  
14. </bean>

       模板默认以前缀“#{”开头,以后缀“}”结尾,且不允许嵌套,如“#{'Hello'#{world}}”错误,如“#{'Hello' + world}”中“world”默认解析为Bean。当然可以使用“@bean”引用了。

 

       接下来测试一下吧:

 



java代码:

查看 复制到剪贴板 打印


1. @Test  
2. public void testXmlExpression() {  
3. new ClassPathXmlApplicationContext("chapter5/el1.xml");  
4. "hello1", String.class);  
5. "hello2", String.class);  
6. "hello3", String.class);  
7. "Hello World!", hello1);  
8. "Hello World!", hello2);  
9. "Hello World!", hello3);  
10. }

 

       是不是很简单,除了XML配置方式,Spring还提供一种注解方式@Value,接着往下看吧。

5.4.2  注解风格的配置

       基于注解风格的SpEL配置也非常简单,使用@Value注解来指定SpEL表达式,该注解可以放到字段、方法及方法参数上。

       测试Bean类如下,使用@Value来指定SpEL表达式:

 



java代码:

查看 复制到剪贴板 打印


1. package cn.javass.spring.chapter5;  
2. import org.springframework.beans.factory.annotation.Value;  
3. public class SpELBean {  
4. @Value("#{'Hello' + world}")  
5. private String value;  
6. //setter和getter由于篇幅省略,自己写上  
7. }

 

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

 



java代码:

查看 复制到剪贴板 打印


1. <?xml version="1.0" encoding="UTF-8"?>  
2. <beans  xmlns="http://www.springframework.org/schema/beans"  
3. "http://www.w3.org/2001/XMLSchema-instance"  
4. "http://www.springframework.org/schema/context"  
5.         xsi:schemaLocation="  
6. //www.springframework.org/schema/beans  
7. //www.springframework.org/schema/beans/spring-beans-3.0.xsd  
8. //www.springframework.org/schema/context  
9. http://www.springframework.org/schema/context/spring-context-3.0.xsd">  
10.    <context:annotation-config/>  
11. "world" class="java.lang.String">  
12. "#{' World!'}"/>  
13.    </bean>  
14. "helloBean1" class="cn.javass.spring.chapter5.SpELBean"/>  
15. "helloBean2" class="cn.javass.spring.chapter5.SpELBean">  
16. "value" value="haha"/>  
17.    </bean>  
18. </beans>


 

<context:annotation-config/>”来开启对注解的支持。

 

       有了配置文件那开始测试吧:

 



java代码:

查看 复制到剪贴板 打印



    1. @Test  
    2. public void testAnnotationExpression() {  
    3. new ClassPathXmlApplicationContext("chapter5/el2.xml");  
    4. "helloBean1", SpELBean.class);  
    5. "Hello World!", helloBean1.getValue());  
    6. "helloBean2", SpELBean.class);  
    7. "haha", helloBean2.getValue());  
    8. }


     

           其中“helloBean1 ”值是SpEL表达式的值,而“helloBean2”是通过setter注入的值,这说明setter注入将覆盖@Value的值。

     

    5.4.3  在Bean定义中SpEL的问题

           如果有同学问“#{我不是SpEL表达式}”不是SpEL表达式,而是公司内部的模板,想换个前缀和后缀该如何实现呢?

           那我们来看下Spring如何在IoC容器内使用BeanExpressionResolver接口实现来求值SpEL表达式,那如果我们通过某种方式获取该接口实现,然后把前缀后缀修改了不就可以了。

           此处我们使用BeanFactoryPostProcessor接口提供postProcessBeanFactory回调方法,它是在IoC容器创建好但还未进行任何Bean初始化时被ApplicationContext实现调用,因此在这个阶段把SpEL前缀及后缀修改掉是安全的,具体代码如下:

     



    java代码:

    查看 复制到剪贴板 打印


    1. package cn.javass.spring.chapter5;  
    2. import org.springframework.beans.BeansException;  
    3. import org.springframework.beans.factory.config.BeanFactoryPostProcessor;  
    4. import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;  
    5. import org.springframework.context.expression.StandardBeanExpressionResolver;  
    6. public class SpELBeanFactoryPostProcessor implements BeanFactoryPostProcessor {  
    7. @Override  
    8. public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)  
    9. throws BeansException {  
    10.         StandardBeanExpressionResolver resolver = (StandardBeanExpressionResolver) beanFactory.getBeanExpressionResolver();  
    11. "%{");  
    12. "}");  
    13.     }  
    14. }

     

        首先通过 ConfigurableListableBeanFactory的getBeanExpressionResolver方法获取BeanExpressionResolver实现,其次强制类型转换为StandardBeanExpressionResolver,其为Spring默认实现,然后改掉前缀及后缀。

     

           开始测试吧,首先准备配置文件(chapter5/el3.xml):

     



    java代码:

    查看 复制到剪贴板 打印


    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <beans  xmlns="http://www.springframework.org/schema/beans"  
    3. "http://www.w3.org/2001/XMLSchema-instance"  
    4. "http://www.springframework.org/schema/context"  
    5.         xsi:schemaLocation="  
    6. //www.springframework.org/schema/beans  
    7. //www.springframework.org/schema/beans/spring-beans-3.0.xsd  
    8. //www.springframework.org/schema/context  
    9. //www.springframework.org/schema/context/spring-context-3.0.xsd">  
    10.    <context:annotation-config/>  
    11. class="cn.javass.spring.chapter5.SpELBeanFactoryPostProcessor"/>  
    12. "world" class="java.lang.String">  
    13. "%{' World!'}"/>  
    14.    </bean>  
    15. "helloBean1" class="cn.javass.spring.chapter5.SpELBean"/>  
    16. "helloBean2" class="cn.javass.spring.chapter5.SpELBean">  
    17. "value" value="%{'Hello' + world}"/>  
    18.    </bean>  
    19. </beans>


     

           配置文件和注解风格的几乎一样,只有SpEL表达式前缀变为“%{”了,并且注册了“cn.javass.spring.chapter5.SpELBeanFactoryPostProcessor”Bean,用于修改前缀和后缀的。

           写测试代码测试一下吧:

     



    java代码:

    查看 复制到剪贴板 打印


    1. @Test  
    2. public void testPrefixExpression() {  
    3. new ClassPathXmlApplicationContext("chapter5/el3.xml");  
    4. "helloBean1", SpELBean.class);  
    5. "#{'Hello' + world}", helloBean1.getValue());  
    6. "helloBean2", SpELBean.class);  
    7. "Hello World!", helloBean2.getValue());  
    8. }

     

     

           此处helloBean1 中通过@Value注入的“#{'Hello' + world}”结果还是“#{'Hello' + world}”说明不对其进行SpEL表达式求值了,而helloBean2使用“%{'Hello' + world}”注入,得到正确的“"Hello World!”。