本文爲轉載學習java
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 ,接着往下看吧。學習
基於註解風格的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的值。
若是有同窗問「#{我不是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!」。