spring 使用Spring表达式(Spring EL)
Spring还提供了更灵活的注入方式,那就是Spring表达式,实际上Spring EL远比以上注入方式强大,我们需要学习它。Spring EL拥有很多功能。
使用Bean的id来引用Bean。
•调用指定对象的方法和访问对象的属性。
•进行运算。
•提供正则表达式进行匹配。
•集合配置。
这些都是Spring表达式的内容,使用Spring表达式可以获得比使用Properties文件更为强大的装配功能,只是有时候为了方便测试可以使用Spring EL定义的解析类进行测试,为此我们先来认识它们。
Spring EL相关的类
简要介绍Spring EL的相关类,以便我们进行测试和理解。首先是ExpressionParser接口,它是一个表达式的解析接口,既然是一个接口,那么它就不具备任何具体的功能,显然Spring会提供更多的实现类
代码清单:举例说明Spring EL的使用
//表达式解析器
ExpressionParser parser = new SpelExpressionParser();
// 设置表达式
Expression exp = parser.parseExpression("'hello world'");
String str = (String) exp.getValue();
System.out.println(str);
//通过EL访问普通方法
exp = parser.parseExpression("'hello world'.charAt(0)");
char ch = (Character) exp.getValue();
System.out.println(ch);
//通过EL访问的getter方法
exp = parser.parseExpression("'hello world'.bytes");
byte[] bytes = (byte[]) exp.getValue();
System.out.println(bytes);
//通过EL访问属性,相当于"hello world".getBytes().length
exp = parser.parseExpression("'hello world'.bytes.length");
int length = (Integer) exp.getValue();
System.out.println(length);
exp = parser.parseExpression("new String('abc')");
String abc = (String) exp.getValue();
System.out.println(abc); //表达式解析器
ExpressionParser parser = new SpelExpressionParser();
//创建角色对象
Role2 role = new Role2(1L, "role_name", "note");
Expression exp = parser.parseExpression("note");
//相当于从role中获取备注信息
String note = (String) exp.getValue(role);
System.out.println(note);
//变量环境类,并且将角色对象role作为其根节点
EvaluationContext ctx = new StandardEvaluationContext(role);
//变量环境类操作根节点
parser.parseExpression("note").setValue(ctx, "new_note");
//获取备注,这里的String.class指明,我们希望返回的是一个字符串
note = parser.parseExpression("note").getValue(ctx, String.class);
System.out.println(note);
//调用getRoleName方法
String roleName = parser.parseExpression("getRoleName()").getValue(ctx, String.class);
System.out.println(roleName);
//新增环境变量
List<String> list = new ArrayList<String>();
list.add("value1");
list.add("value2");
//给变量环境增加变量
ctx.setVariable("list", list);
//通过表达式去读/写环境变量的值
parser.parseExpression("#list[1]").setValue(ctx, "update_value2");
System.out.println(parser.parseExpression("#list[1]").getValue(ctx));
EvaluationContext使用了它的实现类StandardEvaluationContext,进行了实例化,在构造方法中将角色对象传递给它了,那么估值内容就会基于这个类进行解析。所以后面表达式的setValue和getValue方法都把这个估值内容传递进去,这样就能够读/写根节点的内容了,并且通过getRole()的例子,还可以知道它甚至能够支持方法的调用。为了更加灵活,估值内容还支持了其他变量的新增和操作,正如代码中创建了一个List,并且把List用估值内容的setVariable方法设置,其键为"list",这样就允许我们在表达式里面通过#list去引用它,而给出的下标1,则是代表引用List的第二个元素(list是以下标0标识第一个元素的)。
上面介绍了Spring具有对表达式的解析功能,Spring EL最重要的功能就是对Bean属性进行注入,让我们以注解的方式为主去学习它们。
Bean的属性和方法
使用注解的方式需要用到注解@Value,在属性文件的读取中使用的是“$”,而在Spring EL中则使用“#”。下面以角色类为例进行讨论,我们可以这样初始化它的属性,如代码清单所示。
代码清单:使用Spring EL初始化角色类
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component; @Component("role2")
public class Role2 { //赋值long型
@Value("#{2}")
private Long id;
//字符串赋值
@Value("#{'role_name_2'}")
private String roleName;
//字符串赋值
@Value("#{'note_2'}")
private String note;
}
代码清单:通过Spring EL引用role的属性,调用其方法
@Component("elBean")
public class ElBean { //通过beanName获取bean,然后注入
@Value("#{role2}")
private Role2 role2; //获取bean的属性id
@Value("#{role2.id}")
private Long id; //调用bean的getNote方法,获取角色名称
// @Value("#{role.getNote().toString()}")
@Value("#{role2.getNote()?.toString()}")
private String note; @Value("#{T(Math).PI}")
private double pi; @Value("#{T(Math).random()}")
private double random; @Value("#{role.id+1}")
private int num;
}
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfig3.class);
Role2 role2 = context.getBean(Role2.class);
System.out.println(role2.toString());
ElBean elBean = context.getBean(ElBean.class);
System.out.println(elBean.toString());
使用类的静态常量和方法
有时候我们可能希望使用一些静态方法和常量,比如圆周率π,而在Java中就是Math类的PI常量了,需要注入它十分简单,在ElBean中如同下面一样操作就可以了:
@Value("#{T(Math).PI}")
private double pi;
这里的Math代表的是java.lang.*包下的Math类。当在Java代码中使用该包是不需要先使用import关键字引入的,对于Spring EL也是如此。如果在Spring中使用一个非该包的内容,那么要给出该类的全限定名,需要写成类似这样:
@Value("#{T(java.lang.Math).PI}")
private double pi;
同样,有时候使用Math类的静态方法去生产随机数(0到1之间的随机双精度数字),这个时候就需要使用它的random方法了,比如:
@Value("#{T(Math).random()}")
private double random;
这样就可以通过调用类的静态方法加载对应的数据了。
Spring EL运算
上面讨论了如何获取值,除此之外Spring EL还可以进行运算,比如在ElBean上增加一个数字num,其值默认为要求是角色编号(id)+1,那么我们就可以写成:
@Value("#{role.id+1}")
private int num;
有时候“+”运算符也可以运用在字符串的连接上,比如下面的这个字段,把角色对象中的属性roleName和note相连:
@Value("#{role.roleName + role.note}")
private String str;
这样就能够得到一个角色名称和备注相连接的字符串。比较两个值是否相等,比如角色id是否为1,角色名称是否为"role_name_001"。数字和字符串都可以使用“eq”或者“==”进行相等比较。除此之外,还有大于、小于等数学运算,比如:
@Value("#{role.id == 1}")
private boolean equalNum;
@Value("#{role.note eq 'note_1'}")
private boolean eqaulString;
@Value("#{role.id > 2}")
private boolean greater;
@Value("#{role.id < 2}")
private boolean less;
在Java中,也许你会怀念三目运算,比如,如果角色编号大于1,那么取值5,否则取值1,那么在Java中可以写成:
int max = (role.getId()>1? 5:1);
如果角色的备注为空,我们给它一个默认的初始值“note”,使用Java则写成:
String defaultString = (role.getNote() == null? "hello" : role.getNote());
下面让我们通过String EL去实现上述的功能。
@Value("#{role.id > 1 ? 5 : 1}")
private int max;
@Value("#{role.note?: 'hello'}")
private String defaultString;
实际上Spring EL的功能远不止这些,上面只介绍了一些最基础、最常用的功能,熟练运用它还需要读者们多动手实践。
文章来源:ssm10.10
spring 使用Spring表达式(Spring EL)的更多相关文章
- Spring Security -SpEL表达式
Spring Security -SpEL表达式 开启SpEL表达式 <!-- use-expressions是否开启 SpEL表达式 o.s.s.web.access.expression.W ...
- Spring AOP切点表达式用法总结
1. 简介 面向对象编程,也称为OOP(即Object Oriented Programming)最大的优点在于能够将业务模块进行封装,从而达到功能复用的目的.通过面向对象编程,不同的模 ...
- Spring定时器corn表达式详解
1.结构 Spring定时器corn表达式详解 2.各字段的含义 字段 允许值 允许的特殊字符 秒 0~59 - * / 分 0~59 - * / 小时 0~23 - * / 日期 1~31 - * ...
- Spring系列1:Spring基本概念
本文内容 什么是Spring? 为什么学Spring? 本系列包含哪些技术? 本系列适合哪些人? 什么是Spring? 基本概念 Spring 框架为现代基于 Java 的企业应用程序提供了一个全面的 ...
- [Spring]支持注解的Spring调度器
概述 如果想在Spring中使用任务调度功能,除了集成调度框架Quartz这种方式,也可以使用Spring自己的调度任务框架. 使用Spring的调度框架,优点是:支持注解(@Scheduler),可 ...
- Spring学习1-初识Spring
一.简介 1.Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架.它的主要目得是简化企业开发. 2.为何要使用Spring? ...
- Spring实战1:Spring初探
主要内容 Spring的使命--简化Java开发 Spring容器 Spring的整体架构 Spring的新发展 现在的Java程序员赶上了好时候.在将近20年的历史中,Java的发展历经沉浮.尽管有 ...
- Spring Boot中使用 Spring Security 构建权限系统
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,为应用系统提供声明式的安全 ...
- Spring框架学习02——Spring IOC 详解
1.Spring IOC的基本概念 IOC(Inverse of Control)反转控制的概念,就是将原本在程序中手动创建对象的控制权,交由Spring框架管理.当某个Java对象(调用者)需要调用 ...
- spring AOP 之一:spring AOP功能介绍
一.AOP简介 AOP:是一种面向切面的编程范式,是一种编程思想,旨在通过分离横切关注点,提高模块化,可以跨越对象关注点.Aop的典型应用即spring的事务机制,日志记录.利用AOP可以对业务逻辑的 ...
随机推荐
- drf框架 - 过滤组件 | 分页组件 | 过滤器插件
drf框架 接口过滤条件 群查接口各种筛选组件数据准备 models.py class Car(models.Model): name = models.CharField(max_length=16 ...
- python 之类、self
类是什么 可以视为种类或者类型的同义词.所有的对象都属于某一个类,称为类的实例. 例如:鸟就是"鸟类"的实例.这就是一个有很多子类的一般(抽象)类:看到的鸟可能属于子类" ...
- 完美字符子串 单调队列预处理+DP线段树优化
题意:有一个长度为n的字符串,每一位只会是p或j.你需要取出一个子串S(注意不是子序列),使得该子串不管是从左往右还是从右往左取,都保证每时每刻已取出的p的个数不小于j的个数.如果你的子串是最长的,那 ...
- LightOJ - 1246 - Colorful Board(DP)
链接: https://vjudge.net/problem/LightOJ-1246 题意: You are given a rectangular board. You are asked to ...
- 留言板welcome here friends!
欢迎留言!!! 另附本人信息栏 \(cnblogs\): ShineEternal \(洛谷\):vercont \(CSDN\) \(blog\): ShineEternal \(github\) ...
- AtCoder Grand Contest 012题解
传送门 \(A\) 肯定是后面每两个陪最前面一个最优 typedef long long ll; const int N=5e5+5; int a[N],n;ll res; int main(){ s ...
- LOJ2719. 「NOI2018」冒泡排序 [组合计数]
LOJ 思路 这题我看着题解还搞了几个小时?我也不知道自己在干啥-- 首先你要通过出色的分析能力得到一个结论:一个排列合法当且仅当它的最长下降子序列长度不超过2. 证明?懒得写了. 然后我们不管字典序 ...
- A2T和T2A,===string和CString互转 方法一:--用宏的方式
USES_CONVERSION它是在堆栈上分配空间的,也就是说你在你在函数未结束就不会被释放掉.所有要注意不要在一个函数中用while循环执行它,不然栈空间就马上会分配完(栈空间一般只有2M,很小). ...
- Django基础(1)-虚拟环境的安装及配置
virtualenv介绍 (1)做什么的?virtualenv是用于创建独立的python环境,使得多个python应用彼此独立: (2)优点: a)使不同应用开发环境独立 b)环境升级不影响其他应用 ...
- 2、Apache(httpd)之一 三种工作模式
httpd的特性: 高度模块化:core + modules 模块化设计DSO:Dynamic Shared Object MPM:Multipath Processing Modules 多路处理模 ...