开涛spring3(5.4) - Spring表达式语言 之 5.4在Bean定义中使用EL

5.4.1  xml风格的配置

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

首先看下配置方式(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”引用了。

接下来测试一下吧:

    @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表达式:

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

    <?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!”。

时间: 2024-08-29 10:21:27

开涛spring3(5.4) - Spring表达式语言 之 5.4在Bean定义中使用EL的相关文章

开涛spring3(5.3) - Spring表达式语言 之 5.3 SpEL语法

5.3  SpEL语法 5.3.1  基本表达式 一.字面量表达式: SpEL支持的字面量包括:字符串.数字类型(int.long.float.double).布尔类型.null类型. 类型 示例 字符串 String str1 = parser.parseExpression("'Hello World!'").getValue(String.class); String str2 = parser.parseExpression("\"Hello World!\

开涛spring3(12.3) - 零配置 之 12.3 注解实现Bean定义

12.3  注解实现Bean定义 12.3.1  概述 前边介绍的Bean定义全是基于XML方式定义配置元数据,且在[12.2注解实现Bean依赖注入]一节中介绍了通过注解来减少配置数量,但并没有完全消除在XML配置文件中的Bean定义,因此有没有方式完全消除XML配置Bean定义呢? Spring提供通过扫描类路径中的特殊注解类来自动注册 Bean定义.同注解驱动事务一样需要开启自动扫描并注册Bean定义支持,使用方式如下(resources/chapter12/ componentDefin

开涛spring3(12.2) - 零配置 之 12.2 注解实现Bean依赖注入

12.2  注解实现Bean依赖注入 12.2.1  概述 注解实现Bean配置主要用来进行如依赖注入.生命周期回调方法定义等,不能消除XML文件中的Bean元数据定义,且基于XML配置中的依赖注入的数据将覆盖基于注解配置中的依赖注入的数据. Spring3的基于注解实现Bean依赖注入支持如下三种注解: Spring自带依赖注入注解: Spring自带的一套依赖注入注解: JSR-250注解:Java平台的公共注解,是Java EE 5规范之一,在JDK6中默认包含这些注解,从Spring2.

开涛spring3(12.4) - 零配置 之 12.4 基于Java类定义Bean配置元数据

12.4  基于Java类定义Bean配置元数据 12.4.1  概述 基于Java类定义Bean配置元数据,其实就是通过Java类定义Spring配置元数据,且直接消除XML配置文件. 基于Java类定义Bean配置元数据中的@Configuration注解的类等价于XML配置文件,@Bean注解的方法等价于XML配置文件中的Bean定义. 基于Java类定义Bean配置元数据需要通过AnnotationConfigApplicationContext加载配置类及初始化容器,类似于XML配置文

开涛spring3(9.2) - Spring的事务 之 9.2 数据库事务概述

9.2.1  概述 Spring框架支持事务管理的核心是事务管理器抽象,对于不同的数据访问框架(如Hibernate)通过实现策略接口 PlatformTransactionManager,从而能支持各种数据访问框架的事务管理,PlatformTransactionManager 接口定义如下: public interface PlatformTransactionManager { TransactionStatus getTransaction(TransactionDefinition

开涛spring3(9.2) - Spring的事务 之 9.3 编程式事务

9.3  编程式事务 9.3.1  编程式事务概述 所谓编程式事务指的是通过编码方式实现事务,即类似于JDBC编程实现事务管理. Spring框架提供一致的事务抽象,因此对于JDBC还是JTA事务都是采用相同的API进行编程.

Spring学习笔记--Spring表达式语言SpEL

Spring3引入了Spring表达式语言(Spring Expression Language,SpEL).SpEL是一种强大的.简洁的装配Bean的方式,它通过运行期执行的表达式将值装配到Bean的属性或构造器参数中.字面值我们可以在<property>元素的value属性中使用#{}界定符将值装配到Bean的属性中. <property name="count" value="#{5}" /> 浮点型数字一样可以出现在SpEL表达式中.

Spring表达式语言SpEL简介

Spring3引入了Spring表达式语言(Spring Expression Language,SpEL). SpEL有很多特性,比较常用的包括: 1.使用bean的id来引用bean, 下面这个例子就是将卧室这个bean通过SpEL注入到house这个bean的bedroom属性中. <bean id="bedroom" class="go.derek.Bedroom"/> <bean id="house" class=&q

开涛spring3(5.1&amp;5.2) - Spring表达式语言 之 5.1 概述 5.2 SpEL基础

5.1  概述 5.1.1  概述 Spring表达式语言全称为“Spring Expression Language”,缩写为“SpEL”,类似于Struts2x中使用的OGNL表达式语言,能在运行时构建复杂表达式.存取对象图属性.对象方法调用 等等,并且能与Spring功能完美整合,如能用来配置Bean定义. 表达式语言给静态Java语言增加了动态功能. SpEL是单独模块,只依赖于core模块,不依赖于其他模块,可以单独使用. 5.1.2  能干什么 表达式语言一般是用最简单的形式完成最主