1、SpEL表达式
从spring3开始引入了spring表达式语言,它可能以一种弱小而间接的形式将值拆卸到Bean属性和结构器参数中,再这个过程中所应用的表达式会在运行时计算失去值。应用SpEL能够实现超乎设想的拆卸成果,这是其余拆卸技术很难做到的。SpEL个性如下
- 应用bean的ID来援用bean;
- 应用办法和拜访对象的属性;
- 对值进行算数、关系和逻辑运算;
- 正则表达式匹配;
- 汇合操作。
SpEL表达式要放到“#{...}”中
2、用法
SpEL有三种用法,一种是在注解@Value中;一种是XML配置;最初一种是在代码块中应用Expression。
2.1 @Value
//@Value能润饰成员变量和办法形参 //#{}内就是表达式的内容
@Value("#{表达式}") public String arg;
如果润饰成员变量,是从Spring容器中依照SpEL表达式筛选批改数据后,赋值给所润饰的变量;如果润饰办法形参,则是过滤传进来的参数值。
- <bean>配置
<bean id="xxx" class="com.java.XXXXX.xx">
<!-- 同@Value,#{}内是表达式的值,可放在property或constructor-arg内 --><property name="arg" value="#{表达式}">
</bean>
- 用法跟注解@ Value润饰形参相似
- Expression
; "复制代码")
import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; public class SpELTest { public static void main(String[] args) { //创立ExpressionParser解析表达式
ExpressionParser parser = new SpelExpressionParser(); //表达式搁置 Expression exp = parser.parseExpression("表达式"); //执行表达式,默认容器是spring自身的容器:ApplicationContext Object value = exp.getValue(); /**如果应用其余的容器,则用上面的办法*/ //创立一个虚构的容器EvaluationContext StandardEvaluationContext ctx = new StandardEvaluationContext(); //向容器内增加bean BeanA beanA = new BeanA(); ctx.setVariable("bean_id", beanA); //setRootObject并非必须;一个EvaluationContext只能有一个RootObject,援用它的属性时,能够不加前缀
ctx.setRootObject(XXX); //getValue有参数ctx,从新的容器中依据SpEL表达式获取所需的值
Object value = exp.getValue(ctx);}
}
; "复制代码")
用法比拟灵便,能够在代码中应用SpEL进行数据的过滤和批改
3、表达式语法
- 间接量表达式
"#{'Hello World'}"
- 间接应用java代码new/instance of
此办法只能是java.lang 下的类才能够省略包名
Expression exp = parser.parseExpression("new Spring('Hello World')");
- 应用T(Type)
应用“T(Type)”来示意java.lang.Class实例,同样,只有java.lang 下的类才能够省略包名。此办法个别用来援用常量或静态方法
parser.parseExpression("T(Integer).MAX_VALUE");
- 变量
获取容器内的变量,能够应用“#bean_id”来获取。有两个非凡的变量,能够间接应用。
- #this 应用以后正在计算的上下文
#root 援用容器的root对象
String result2 = parser.parseExpression("#root").getValue(ctx, String.class);
String s = new String("abcdef"); ctx.setVariable("abc",s); //取id为abc的bean,而后调用其中的substring办法 parser.parseExpression("#abc.substring(0,1)").getValue(ctx, String.class);
- 办法调用
与Java代码没有什么区别,可见下面的例子
能够自定义办法,如下:
Method parseInt = Integer.class.getDeclaredMethod("parseInt", String.class);
ctx.registerFunction("parseInt", parseInt);
ctx.setVariable("parseInt2", parseInt);
String expression1 = "#parseInt('3') == #parseInt2('3')";“registerFunction”和“setVariable”都能够注册自定义函数,然而两个办法的含意不一样,举荐应用“registerFunction”办法注册自定义函数。
- 运算符表达式
算数表达式(“1+2-3*4/2″)
比拟表达式(“1>2”)
逻辑表达式(“2>1 and (!true or !false)”)
赋值表达式(“#variableName=value”)
三目表达式(“表达式1?表达式2:表达式3”)
正则表达式(“123′ matches ‘d{3}”)
等运算符,都能够间接放在SpEL中- Elvis运算符
是三目运算符的非凡写法,能够防止null报错的状况
name != null? name : "other"
//简写为:name?:"other"
- 平安保障
为了防止操作对象自身可能为null,取属性时报错,定义语法
语法: “对象?.变量|办法”
list?.length
当对象为null时,间接返回“null”,不会抛出NullPointerException
- 汇合定义
应用“{表达式,……}”定义List,如“{1,2,3}”
对于字面量表达式列表,SpEL会应用java.util.Collections.unmodifiableList 办法将列表设置为不可批改。
List<Integer> result1 = parser.parseExpression("{1,2,3}").getValue(List.class);
- 汇合拜访
SpEL目前反对所有汇合类型和字典类型的元素拜访
语法:“汇合[索引]”、“map[key]”
; "复制代码")
EvaluationContext context = new StandardEvaluationContext(); //即list.get(0)
int result1 = parser.parseExpression("{1,2,3}[0]").getValue(int.class); //list获取某一项
Collection<Integer> collection = new HashSet<Integer>();
collection.add(1);
collection.add(2);context.setVariable("collection", collection); int result2 = parser.parseExpression("#collection[1]").getValue(context, int.class); //map获取
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);context.setVariable("map", map); int result3 = parser.parseExpression("#map['a']").getValue(context, int.class);
; "复制代码")
- 汇合批改
能够应用赋值表达式或Expression接口的setValue办法批改;
//赋值语句
int result = parser.parseExpression("#array[1] = 3").getValue(context, int.class); //serValue办法
parser.parseExpression("#array[2]").setValue(context, 4);- 汇合抉择
通过肯定的规定对及格进行筛选,结构出另一个汇合
语法:“(list|map).?[抉择表达式]”
抉择表达式后果必须是boolean类型,如果true则抉择的元素将增加到新汇合中,false将不增加到新汇合中。
parser.parseExpression("#collection.?[#this>2]").getValue(context, Collection.class);
下面的例子从数字的collection汇合中选出数字大于2的值,从新组装成了一个新的汇合
- 汇合投影
依据汇合中的元素中通过抉择来结构另一个汇合,该汇合和原汇合具备雷同数量的元素
语法:“SpEL应用“(list|map).![投影表达式]”
; "复制代码")
public class Book { public String name; //书名
public String author; //作者public String publisher; //出版社public double price; //售价public boolean favorite; //是否喜爱
}
; "复制代码")
; "复制代码")
public class BookList {
@Autowired protected ArrayList<Book> list = new ArrayList<Book>() ; protected int num = 0;
}
; "复制代码")
将BookList的实例映射为bean:readList,在另一个bean中注入时,进行投影
//从readList的list下筛选出favorite为true的子集合,再将他们的name字段投为新的list@Value("#{list.?[favorite eq true].![name]}") private ArrayList<String> favoriteBookName;