阅读背景:

Spring/Boot/Cloud系列知识(5)——Spring EL(1)

来源:互联网 

1、Spring EL 概述

Spring EL是Spring Expression Language的简称,中文称作Spring表达式语言。Spring EL并不单单指代某一种特定的表达式格式,而是对Spring中字符串表达式的一个概要性称呼。Spring EL基本功能由Spring核心包提供支持(spring-core组件和spring-context组件),并且不同的组件还对Spring EL的基本功能提供扩展。本文(及后续一文)主要对读者会在实际工作中使用到的Spring EL 进行讲述,并在最后结合一个使用Spring EL 完成自定义注解实例。

2、Spring EL 基本使用

Spring EL 的使用非常灵活,并且主要由“@Value”注解标记进行支撑。“@Value”注解可以在属性、方法上使用,通过这个注解可以基于IOC容器中的bean对象、对象属性、对象方法、操作符计算结果、正则表达式匹配结果、应用程序配置结果、操作系统环境变量配置结果等等,对目标属性、方法入参进行赋值。

2.1、Spring EL 引用固定值

......
@Component("BaseSpel")
public class BaseSpel {
......

/**
* 为这个存在于IOC容器中的对象的myValue1属性赋一个固定的字符串"string value"
*/

@Value("string value")
private String myValue1;
/**
* 为这个存在于IOC容器中的对象的myValue2属性赋一个固定的整型值"100"
*/

@Value("100")
private Integer myValue2;

......
}

使用“@Value”注解基于固定值对目标属性进行赋值的示例非常简单,虽然这样的赋值方式不经常在实际工程中使用(因为赋一个固定值基本没有意义),但通过这个简单示例读者可以热热身。

2.2、Spring EL引用对象、对象属性和对象方法

这种赋值方式在正式系统开发过程中使用频率一般,这里不用过多描述,直接上代码示例就行:

  • 这是一个存储在IOC容器中的普通Bean对象:
/**
* 这是一个存储在IOC容器中的普通对象
* @author yinwenjie
*/

@Component("myPojo")
public class MyPojo {
......
@Value("a")
private String a;

@Value("b")
private String b;

// 这是一个没有任何入参的方法
public String doHandle() {
return "111111";
}

// 这是一个带有一个入参的方法
public String doHandle(String param) {
return new Date().toString() + param;
}
......
}
  • 我们使用“@Value”注解进行赋值,在“BaseSpel”这个Bean初始化时,对其中的属性进行初始化。
@Component("BaseSpel")
public class BaseSpel {
......
/**
* 为BaseSpel类中的myPojo属性赋值
*/

@Value("#{myPojo}")
private MyPojo myPojo;

/**
* 这样可以将myPojo bean中的a属性进行赋值
*/

@Value("#{myPojo.a}")
private String myPojo_a;

/**
* 调用myPojo1 bean中的doHandle方法
*/

@Value("#{myPojo.doHandle()}")
private String myPojo_m;

/**
* 调用myPojo bean中的doHandle方法
* 且将myPojo bean中的a属性的值,作为方法调用时的传入参数
*/

@Value("#{myPojo.doHandle(myPojo.a)}")
private String myPojo_n;
......
}

“@Value”注解中的“#{myPojo}”表示将IOC容器中名叫“myPojo”的bean对象进行赋值。这个名叫“myPojo”的信息必须存在。它或者是配置文件中的某个属性,或者是某个保留关键字(例如systemProperties),又或者是IOC容器中的一个bean对象等等,否则会报SpelEvaluationException性质的异常——“Property or field ‘XXXXXX’ cannot be found”。“#{myPojo.a}”表示名叫“myPojo”的bean对象中名叫“a”的属性。将后者的值赋予对象中的myPojo_a属性。

“#{myPojo.doHandle()}”表示使用名叫“myPojo”的bean对象中“doHandle()”方法的调用返回值作为“myPojo_m”属性的赋值结果。当然您还可以设置调用“doHandle()”方法时的参数传入,例如“#{myPojo.doHandle(myPojo.a)}”就是将“myPojo.a”属性的值作为调用方法时的参数进行传入。

请注意,由于Spring IOC容器中名叫“myPojo”的这个bean对象是以单例模式存在,所以无论有多少个Bean通过“@Value”注解获得“myPojo”这个bean中的值,其赋值结果都是一样的(当然调用方法进行赋值时方法中有不同处理的除外)。以下是debug时所显示的“BaseSpel”bean的属性值状态:

2.3、Spring EL中使用操作符

Spring EL支持数学操作符、逻辑操作符、关系操作符等基本的二元操作符和三元操作符。包括(但不限于):’==’、’!=’、“<=”、’>=’、’and’、’or’、’+’、’-‘、’*’、’/’、’%’、’^’等等。

请注意,由于本系列专题的示例都是基于Spring Boot这样免配置组件,所以以上列出的操作符都是在“@Value”这样的注解直接使用的。如果读者使用的是Spring XML这样的配置文件定义bean和依赖关系,那么Spring EL操作符就需要进行转义,例如’<’操作符转义为’&lt’、’>’操作符转义为’&gt’,等等。另外,类似“++”这样的一元操作符Spring EL表达式是不支持的

2.3.1、二元操作符

  • 以下是多个二元操作符的使用示例:
/**
* 对操作符的支持
*/

@Component("opSpel")
public class OpSpel {
......
// == 操作符,可以直接支持字符串的判断
@Value("#{myPojo.a == 'a'}")
private boolean eq;
// != 操作符,也可以支持字符串的判断
@Value("#{myPojo.a != 'yinwenjieb'}")
private boolean noteq;
// “与”操作符
@Value("#{myPojo.a == 'a' and myPojo.a != 'b'}")
private boolean and;
// “或”操作符
@Value("#{myPojo.a == 'a' or myPojo.a == 'b'}")
private boolean or;
// 加法操作
@Value("#{BaseSpel.myValue2 + 1}")
private int addop;
// 减法操作
@Value("#{BaseSpel.myValue2 - 1}")
private int subop;
// 除法操作
@Value("#{BaseSpel.myValue2 / 20}")
private float division;
......
}
  • 以下是debug操作时所显示的“opSpel”bean的属性值状态:

2.3.2、三元操作符

Spring EL除了支持基本的二元表达式(’==’、’!=’、“<=”、’>=’、’and’、’or’、’+’、’-‘、’*’、’/’、’%’、’^’等等),还支持三元表达式。以下是三元操作符的一个使用示例:

/**
* 对操作符的支持
*/

@Component("opSpel")
public class OpSpel {
......
/**
* 三元操作符
* randomNumber()方法将返回一个0.0到1.0的随机数。
* 那么这个三元表达式有50%的几率返回'1';50%的几率返回'2'
*/

@Value("#{BaseSpel.randomNumber() < 0.5 ? '1':'2'}")
......
}
  • 以上代码片段中调用的randomNumber()方法,在BaseSpel bean下的定义如下:
@Component("BaseSpel")
public class BaseSpel {
......
public float randomNumber() {
return new Random().nextFloat();
}
......
}

2.4、Spring EL中使用正则表达式

Spring EL支持正则表达式,且这种方式在正式系统的开发中经常使用。本文不会讲解正则表达式本身的使用技巧,如果读者不清楚正则表达式的使用方式,请另外参考资料。

  • 以下是一个使用正则表达式的简单示例:

在一个名叫“BaseSpel”的Bean中定义了一个方法,这个方法中随机取出4个不同的用户名,如下所示:

@Component("BaseSpel")
public class BaseSpel {
......
// 随机获取一个用户名
public String randomUserName() {
String userNames[] = new String[]{"yinwenjie2009","yin-wen-jie","yinwenjie-2009","Yinwenjie2009"};
return userNames[new Random().nextInt(4)];
}
......
}

然后接着在名叫“opSpel”的Bean中,通过“@Value”注解调用这个方法,如下所示:

@Component("opSpel")
public class OpSpel {
......
@Value("#{BaseSpel.randomUserName() matches '^\\w+$'}")
private boolean username;
......
}

以上代码中对“@Value”注解的使用大致的意思是,调用“opSpel”这个bean中的randomUserName()方法随机获得四个用户名”yinwenjie2009”、”yin-wen-jie”、”yinwenjie-2009”或者”Yinwenjie2009”,其中”yin-wen-jie”和”yinwenjie-2009”这两个用户名是不满足正则表达式的“^\w+$”规则的。于是username属性的值就会返回false(其它情况返回true)。

  • 再来一个三元表达式和和正则表达式混用的Spring EL示例,这里就只给代码,不再进行单独说明了:
@Component("opSpel")
public class OpSpel {
......
@Value("#{BaseSpel.randomUserName() matches '^\\w+$'?'1':'2'}")
private String userName;
......
}

======================================
(后文内容包括:Spring EL集合、Spring EL 和AOP切面配置)


分享到: