# 【第五章】Spring表達式語言 之 5.4在Bean定義中使用EL—跟我學spring3
##
### 5.4.1? xml風格的配置
SpEL支持在Bean定義時注入,默認使用“#{SpEL表達式}”表示,其中“#root”根對象默認可以認為是ApplicationContext,只有ApplicationContext實現默認支持SpEL,獲取根對象屬性其實是獲取容器中的Bean。
首先看下配置方式(chapter5/el1.xml)吧:
1. <bean?id="world"?class="java.lang.String">??
2. <constructor-arg?value="#{'?World!'}"/>??
3. </bean>??
4. <bean?id="hello1"?class="java.lang.String">??
5. <constructor-arg?value="#{'Hello'}#{world}"/>??
6. </bean>????
7. <bean?id="hello2"?class="java.lang.String">??
8. <constructor-arg?value="#{'Hello'?+?world}"/>??
9. <!--?不支持嵌套的?-->??
10. <!--<constructor-arg?value="#{'Hello'#{world}}"/>-->??
11. </bean>??
12. <bean?id="hello3"?class="java.lang.String">??
13. <constructor-arg?value="#{'Hello'?+?@world}"/>??
14. </bean>??
模板默認以前綴“#{”開頭,以后綴“}”結尾,且不允許嵌套,如“#{'Hello'#{world}}”錯誤,如“#{'Hello' + world}”中“world”默認解析為Bean。當然可以使用“@bean”引用了。
接下來測試一下吧:
1. @Test??
2. public?void?testXmlExpression()?{??
3. ApplicationContext?ctx?=?new?ClassPathXmlApplicationContext("chapter5/el1.xml");??
4. String?hello1?=?ctx.getBean("hello1",?String.class);??
5. String?hello2?=?ctx.getBean("hello2",?String.class);??
6. String?hello3?=?ctx.getBean("hello3",?String.class);??
7. Assert.assertEquals("Hello?World!",?hello1);??
8. Assert.assertEquals("Hello?World!",?hello2);??
9. Assert.assertEquals("Hello?World!",?hello3);??
10. }?????
是不是很簡單,除了XML配置方式,Spring還提供一種注解方式@Value,接著往下看吧。
### 5.4.2? 注解風格的配置
基于注解風格的SpEL配置也非常簡單,使用@Value注解來指定SpEL表達式,該注解可以放到字段、方法及方法參數上。
測試Bean類如下,使用@Value來指定SpEL表達式:
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):
1. <?xml?version="1.0"?encoding="UTF-8"?>??
2. <beans??xmlns="http://www.springframework.org/schema/beans"??
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"??
4. xmlns:context="http://www.springframework.org/schema/context"??
5. xsi:schemaLocation="??
6. http://www.springframework.org/schema/beans??
7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd??
8. http://www.springframework.org/schema/context??
9. http://www.springframework.org/schema/context/spring-context-3.0.xsd">??
10. <context:annotation-config/>??
11. <bean?id="world"?class="java.lang.String">??
12. <constructor-arg?value="#{'?World!'}"/>??
13. </bean>??
14. <bean?id="helloBean1"?class="cn.javass.spring.chapter5.SpELBean"/>??
15. <bean?id="helloBean2"?class="cn.javass.spring.chapter5.SpELBean">??
16. <property?name="value"?value="haha"/>??
17. </bean>??
18. </beans>??
配置時必須使用“**<context:annotation-config/>**”來開啟對注解的支持。
有了配置文件那開始測試吧:
1. @Test??
2. public?void?testAnnotationExpression()?{??
3. ApplicationContext?ctx?=?new?ClassPathXmlApplicationContext("chapter5/el2.xml");??
4. SpELBean?helloBean1?=?ctx.getBean("helloBean1",?SpELBean.class);??
5. Assert.assertEquals("Hello?World!",?helloBean1.getValue());??
6. SpELBean?helloBean2?=?ctx.getBean("helloBean2",?SpELBean.class);??
7. Assert.assertEquals("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前綴及后綴修改掉是安全的,具體代碼如下:
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. resolver.setExpressionPrefix("%{");??
12. resolver.setExpressionSuffix("}");??
13. }??
14. }??
首先通過 ConfigurableListableBeanFactory的getBeanExpressionResolver方法獲取BeanExpressionResolver實現,其次強制類型轉換為StandardBeanExpressionResolver,其為Spring默認實現,然后改掉前綴及后綴。
開始測試吧,首先準備配置文件(chapter5/el3.xml):
1. <?xml?version="1.0"?encoding="UTF-8"?>??
2. <beans??xmlns="http://www.springframework.org/schema/beans"??
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"??
4. xmlns:context="http://www.springframework.org/schema/context"??
5. xsi:schemaLocation="??
6. http://www.springframework.org/schema/beans??
7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd??
8. http://www.springframework.org/schema/context??
9. http://www.springframework.org/schema/context/spring-context-3.0.xsd">??
10. <context:annotation-config/>??
11. <bean?class="cn.javass.spring.chapter5.SpELBeanFactoryPostProcessor"/>??
12. <bean?id="world"?class="java.lang.String">??
13. <constructor-arg?value="%{'?World!'}"/>??
14. </bean>??
15. <bean?id="helloBean1"?class="cn.javass.spring.chapter5.SpELBean"/>??
16. <bean?id="helloBean2"?class="cn.javass.spring.chapter5.SpELBean">??
17. <property?name="value"?value="%{'Hello'?+?world}"/>??
18. </bean>??
19. </beans>??
配置文件和注解風格的幾乎一樣,只有SpEL表達式前綴變為“%{”了,并且注冊了“cn.javass.spring.chapter5.SpELBeanFactoryPostProcessor”Bean,用于修改前綴和后綴的。
寫測試代碼測試一下吧:
1. @Test??
2. public?void?testPrefixExpression()?{??
3. ApplicationContext?ctx?=?new?ClassPathXmlApplicationContext("chapter5/el3.xml");??
4. SpELBean?helloBean1?=?ctx.getBean("helloBean1",?SpELBean.class);??
5. Assert.assertEquals("#{'Hello'?+?world}",?helloBean1.getValue());??
6. SpELBean?helloBean2?=?ctx.getBean("helloBean2",?SpELBean.class);??
7. Assert.assertEquals("Hello?World!",?helloBean2.getValue());??
8. }??????
此處helloBean1 中通過@Value注入的“#{'Hello' + world}”結果還是“#{'Hello' + world}”說明不對其進行SpEL表達式求值了,而helloBean2使用“%{'Hello' + world}”注入,得到正確的“"Hello World!”。
- 跟我學 Spring3
- 【第二章】 IoC 之 2.1 IoC基礎 ——跟我學Spring3
- 【第二章】 IoC 之 2.2 IoC 容器基本原理 ——跟我學Spring3
- 【第二章】 IoC 之 2.3 IoC的配置使用——跟我學Spring3
- 【第三章】 DI 之 3.1 DI的配置使用 ——跟我學spring3
- 【第三章】 DI 之 3.2 循環依賴 ——跟我學spring3
- 【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3
- 【第三章】 DI 之 3.4 Bean的作用域 ——跟我學spring3
- 【第四章】 資源 之 4.1 基礎知識 ——跟我學spring3
- 【第四章】 資源 之 4.2 內置Resource實現 ——跟我學spring3
- 【第四章】 資源 之 4.3 訪問Resource ——跟我學spring3
- 【第四章】 資源 之 4.4 Resource通配符路徑 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.1 概述 5.2 SpEL基礎 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.3 SpEL語法 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.4在Bean定義中使用EL—跟我學spring3
- 【第六章】 AOP 之 6.1 AOP基礎 ——跟我學spring3
- 【第六章】 AOP 之 6.2 AOP的HelloWorld ——跟我學spring3
- 【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.4 基于@AspectJ的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.5 AspectJ切入點語法詳解 ——跟我學spring3
- 【第六章】 AOP 之 6.6 通知參數 ——跟我學spring3
- 【第六章】 AOP 之 6.7 通知順序 ——跟我學spring3
- 【第六章】 AOP 之 6.8 切面實例化模型 ——跟我學spring3
- 【第六章】 AOP 之 6.9 代理機制 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.1 概述 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.2 JDBC模板類 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.3 關系數據庫操作對象化 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.4 Spring提供的其它幫助 ——跟我學spring3【私塾在線原創】
- 【第七章】 對JDBC的支持 之 7.5 集成Spring JDBC及最佳實踐 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.1 概述 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.2 集成Hibernate3 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.3 集成iBATIS ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.4 集成JPA ——跟我學spring3
- 【第九章】 Spring的事務 之 9.1 數據庫事務概述 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.2 事務管理器 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.3 編程式事務 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.4 聲明式事務 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.1 概述 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.2 集成Struts1.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.3 集成Struts2.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.4 集成JSF ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.1 概述 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.2 實現通用層 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.3 實現積分商城層 ——跟我學spring3
- 【第十二章】零配置 之 12.1 概述 ——跟我學spring3
- 【第十二章】零配置 之 12.2 注解實現Bean依賴注入 ——跟我學spring3
- 【第十二章】零配置 之 12.3 注解實現Bean定義 ——跟我學spring3
- 【第十二章】零配置 之 12.4 基于Java類定義Bean配置元數據 ——跟我學spring3
- 【第十二章】零配置 之 12.5 綜合示例-積分商城 ——跟我學spring3
- 【第十三章】 測試 之 13.1 概述 13.2 單元測試 ——跟我學spring3
- 【第十三章】 測試 之 13.3 集成測試 ——跟我學spring3
- 跟我學 Spring MVC
- SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常見問題總結
- Spring Web MVC中的頁面緩存支持 ——跟我學SpringMVC系列
- Spring3 Web MVC下的數據類型轉換(第一篇)——《跟我學Spring3 Web MVC》搶先看
- Spring3 Web MVC下的數據格式化(第二篇)——《跟我學Spring3 Web MVC》搶先看
- 第一章 Web MVC簡介 —— 跟開濤學SpringMVC
- 第二章 Spring MVC入門 —— 跟開濤學SpringMVC
- 第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC
- 第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解 (4)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC
- 跟著開濤學SpringMVC 第一章源代碼下載
- 第二章 Spring MVC入門 源代碼下載
- 第四章 Controller接口控制器詳解 源代碼下載
- 第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(7 完)——跟著開濤學SpringMVC
- 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 源代碼下載 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 注解式控制器運行流程及處理器定義 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- 源代碼下載 第六章 注解式控制器詳解
- SpringMVC3強大的請求映射規則詳解 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- Spring MVC 3.1新特性 生產者、消費者請求限定 —— 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(1)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(2)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC數據類型轉換——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據格式化——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據驗證——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC