MyException - 我的异常网
当前位置:我的异常网» 开源软件 » Spring(23)——SPEL表达式(4)

Spring(23)——SPEL表达式(4)

www.MyException.Cn  网友分享于:2013-09-28  浏览:0次
Spring(23)——SPEL表达式(四)

23.2.24 设置默认值

SpEl表达式中支持“a?:b”这样的语法来设置默认值。其表示如果a不为null时其结果为a,否则就为b。

@Test
public void test24 () {
	ExpressionParser parser = new SpelExpressionParser();
	Assert.assertTrue(parser.parseExpression("#abc?:123").getValue().equals(123));//变量abc不存在
	Assert.assertTrue(parser.parseExpression("1?:123").getValue().equals(1));//数字1不为null
}

23.2.25 安全导航

我们可能经常会使用类似于“a.b.c”这样的用法,表示a的b属性的c属性,但如果a为null或者a的b属性为null时都会出现空指针。为了避免此种情况发生,我们可以在SpEl表达式中使用安全导航,这样当a为null或a的b属性为null时将直接返回null,而不抛出空指针异常。SpEl表达式中安全导航的语法是将点“.”替换为“?.”,即不使用“a.b.c”,而是使用“a?.b?.c”。

@Test
public void test25 () {
	ExpressionParser parser = new SpelExpressionParser();
	Assert.assertNull(parser.parseExpression("null?.abc").getValue());
	Assert.assertNull(parser.parseExpression("T(System)?.getProperty('abc')?.length()").getValue());//数字1不为null
}

23.2.26 获取bean对象

在SpEL表达式里面也可以直接访问bean对象,前提是指定了一个BeanResolver。BeanResolver是一个接口,其只定义了一个方法resolve,用以通过beanName解析为对应的bean对象并返回,具体定义如下。

public interface BeanResolver {

	Object resolve(EvaluationContext context, String beanName) throws AccessException;

}

如果要在SpEL表达式中访问bean对象,我们需要通过StandardEvaluationContext来设置对应的BeanResolver,同时我们需要在SpEL表达式中以“@beanName”的方式来访问对应的bean对象。如下是一段示例代码,我们在表达式中获取到了名称为hello的bean对象,并访问了其getKey()方法。

@Test
public void test26() {
	ExpressionParser parser = new SpelExpressionParser();
	StandardEvaluationContext context = new StandardEvaluationContext();
	context.setBeanResolver(new MyBeanResolver());
	//访问bean名称为hello的bean对象的getKey()方法。
	Object obj = parser.parseExpression("@hello.key").getValue(context);
	System.out.println(obj);
}

private static class MyBeanResolver implements BeanResolver {

	private static ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");
	
	public Object resolve(EvaluationContext context, String beanName)
			throws AccessException {
		return appContext.getBean(beanName);
	}
	
}

23.3 SpelParserConfiguration

在构建SpelExpressionParser时我们可以给其传递一个SpelParserConfiguration对象以对SpelExpressionParser进行配置。其可以用于指定在遇到List或Array为null时是否自动new一个对应的实例,对应SpelParserConfiguration的第一个构造参数;也可以指定在List或Array中对应索引超出了当前索引的最大值时是否自动进行扩充,对应SpelParserConfiguration的第二个构造参数,更多信息请参考Spring的API文档。如下示例中我们就使用了SpelParserConfiguration对象,指定了在对应的List或Array为null时自动new一个对应的对象,并且在对应的索引超出了List或Array当前的最大索引时自动对其进行扩充。所以如下示例中在我们第一次访问User的interests时其为null,之后第二次访问时,由于指定了将自动new对应的对象并且在索引超出时自动进行扩充,所以将new一个List的实例,对应ArrayList,且在索引5不存在时将自动扩充并进行填值,填值时将对List的元素类型String new 6次。所以对于这种情况我们需要保证List或Array中存放的元素类型存在无参构造方法。

class User {
	public List<String> interests;
}

@Test
public void test() {
	User user = new User();
	SpelParserConfiguration parserConfig = new SpelParserConfiguration(true, true);
	ExpressionParser parser = new SpelExpressionParser(parserConfig);
	//第一次为null
	Assert.assertNull(parser.parseExpression("interests").getValue(user));
	//自动new一个List的实例,对应ArrayList,并自动new String()添加6次。
	Assert.assertTrue(parser.parseExpression("interests[5]").getValue(user).equals(""));
	//size为6
	Assert.assertTrue(parser.parseExpression("interests.size()").getValue(user).equals(6));
}

23.4 在bean定义中使用SpEl

在bean定义中使用SpEl表达式的语法是“#{exp}”。exp就是对应的表达式。如下示例中我们定义了一个名为hello的bean,在指定其userDir时我们使用了表达式。

<bean id="hello" class="com.app.Hello">
	<property name="userDir" value="#{T(System).getProperty('user.dir')}"/>
</bean>

对于系统属性而言,在bean定义中使用时有一个内置的变量可以使用叫systemProperties,而且在使用时不需要加“#”,即不需要以“#systemProperties”的形式出现。所以上述示例也可以是如下这样。

<bean id="hello" class="com.elim.learn.spring.bean.Hello">
	<property name="userDir" value="#{systemProperties['user.dir']}"/>
</bean>

23.4.1 引用其它bean的属性

在进行bean定义时,我们也可以通过表达式引用其它bean定义的属性。如下示例中我们就在定义id为world的bean的key属性时通过表达式引用了名为hello的bean的key属性,即world的key属性也将被赋予值“abc”。

<bean id="hello" class="com.app.Hello">
	<property name="key" value="abc"/>
</bean>

<bean id="world" class="com.app.World">
	<property name="key" value="#{hello.key}"/>
</bean>

23.4.2 基于注解配置的使用

在基于注解配置的bean定义中我们也可以使用SpEl表达式进行某些定义。在基于注解配置bean定义时我们可以使用@Value注解定义在方法或属性上来指定对应的值。此时我们就可以使用对应的表达式,当然不使用表达式也是可以的。如下示例中我们就通过@Value指定了userDir和key的值。其中userDir的值的定义使用了SpEl表达式,而key的值的定义是直接定义的。

public class Hello {

	@Value("#{systemProperties['user.dir']}")
	private String userDir;
	@Value("abc")
	private String key;

	public String getUserDir() {
		return userDir;
	}

	public void setUserDir(String userDir) {
		this.userDir = userDir;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

}

(注:本文是基于Spring4.1.0所写)

文章评论

 程序员的样子
程序员的样子
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
我的丈夫是个程序员
我的丈夫是个程序员
如何成为一名黑客
如何成为一名黑客
程序员和编码员之间的区别
程序员和编码员之间的区别
那些争议最大的编程观点
那些争议最大的编程观点
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
每天工作4小时的程序员
每天工作4小时的程序员
程序员的鄙视链
程序员的鄙视链
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
程序员应该关注的一些事儿
程序员应该关注的一些事儿
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
漫画:程序员的工作
漫画:程序员的工作
编程语言是女人
编程语言是女人
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
中美印日四国程序员比较
中美印日四国程序员比较
鲜为人知的编程真相
鲜为人知的编程真相
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
程序员都该阅读的书
程序员都该阅读的书
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
程序员必看的十大电影
程序员必看的十大电影
旅行,写作,编程
旅行,写作,编程
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
老程序员的下场
老程序员的下场
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
10个调试和排错的小建议
10个调试和排错的小建议
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
代码女神横空出世
代码女神横空出世
总结2014中国互联网十大段子
总结2014中国互联网十大段子
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
为什么程序员都是夜猫子
为什么程序员都是夜猫子
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
我是如何打败拖延症的
我是如何打败拖延症的
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有