正文
1. 概述
1.1. 概念
在Spring @Value 属性注入使用总结二中提到使用@Value注入属性值。为了更深入的使用的@Value,我们引入 SpEL。通过Spring的表达式注入更复杂的内容
2. 辅助类
以下演示SpEL的用法需要用到的辅助类: Inventor:测试类
public class Inventor {
private String name;
private String nationality;
private String[] inventions;
private Date birthdate;
private PlaceOfBirth placeOfBirth;
private List<PlaceOfBirth> placeOfBirthList;
private Map<String,Integer> map = new HashMap<String, Integer>();
public Inventor(String name, String nationality) {
GregorianCalendar c= new GregorianCalendar();
this.name = name;
this.nationality = nationality;
this.birthdate = c.getTime();
}
public Inventor(String name, Date birthdate, String nationality) {
this.name = name;
this.nationality = nationality;
this.birthdate = birthdate;
}
/**
* 传入name是否和对象成员变量name相同
* @param name
* @return
*/
public boolean nameIsSame(String name){
return this.name.equals(name);
}
// set/get方法略
}
PlaceOfBirth:Inventor里的成员类
public class PlaceOfBirth {
private String city;
private String country;
public PlaceOfBirth(String city) {
this.city = city;
}
public PlaceOfBirth(String city, String country) {
this(city);
this.country = country;
}
}
启动类,并定义Inventor的值
@SpringBootApplication
@Configurable
public class SpELAnnotationApplication {
public static void main(String[] args) {
SpringApplication.run(SpELAnnotationApplication.class, args);
}
// 初始化测试所需要的对象
@Bean("inventor")
public Inventor getInventor(){
Inventor invertor = new Inventor("name",new Date(),"nationality");
// 设置placeOfBirth
invertor.setPlaceOfBirth(new PlaceOfBirth("city", "country"));
// 设置string数组
invertor.setInventions(new String[]{"inventions_1","inventions_2","inventions_3","inventions_4"});
// 设置PlaceOfBirth的List
List<PlaceOfBirth> placeOfBirthList = new ArrayList<PlaceOfBirth>();
placeOfBirthList.add(new PlaceOfBirth("city_list_1", "country_list_1"));
placeOfBirthList.add(new PlaceOfBirth("city_list_2", "country_list_2"));
placeOfBirthList.add(new PlaceOfBirth("city_list_3", "country_list_3"));
invertor.setPlaceOfBirthList(placeOfBirthList);
// 设置map值
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("mapKey_1", 1);
map.put("mapKey_2", 2);
map.put("mapKey_3", 3);
invertor.setMap(map);
return invertor;
}
}
3. Spring EL 常用语法
这里只使用@Value显示Sp EL的用法,Java代码和XML的用法类似,这样暂时不演示。 Spring EL各种语法,详细如下。
3.1. Literal expressions(文字表达式)
子类又细分为以下类别:
- strings
- numeric
- boolean
- null
具体的用法如下:
// string: 输出 --> Hello World
@Value("#{ 'Hello World' }")
private String stringHello;
// numeric - double: 输出 --> 6.0221415e+23
@Value("#{ 6.0221415E+23 }")
private double numbericDouble;
// numeric - hex: 输出 --> 2147483647
@Value("#{ 0x7FFFFFFF }")
private int numbericInt;
// boolean: 输出 --> true
@Value("#{ true }")
private boolean numberBoolean;
// null: 输出 --> null值
@Value("#{ null }")
private Integer numberNull;
3.2. Types expressions
具体用法如下:
1. 使用特殊操作符T指定java.lang.Class实例
2. 对于java.lang下面的类, T()可以不指定全限定名称
3. T也可以用于调用静态方法
// T指定java.lang.Class实例: 输出 --> java.util.Date
@Value("#{ T(java.util.Date)}")
private Class<?> tDate;
// 对于java.lang下面的类, T()可以不指定全限定名称: 输出 --> java.lang.String
@Value("#{ T(String)}")
private Class<?> tLangString;
// 调用类的静态方法: 输出 --> true
@Value("#{ T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR }")
private boolean tStaticMethod;
3.3. Accessing properties
Accessing properties
// 访问对象inventor的属性name: 输出 --> name
@Value("#{ inventor.name }")
private String propertiesGetObjectMethod;
// 调用对象inventor的成员变量birthdate的getYear()方法: 输出 --> 2017
@Value("#{ inventor.birthdate.Year + 1900}")
private int propertiesGetObjectMemberMethod;
3.4. arrays数组
具体用法如下:
1. 通过索引访问数组对象
2. 初始化数组
// 通过索引访问数组对象: 输出 --> inventions_3
@Value("#{ inventor.inventions[2] }")
private String arraysIndex;
// 初始化数组: 输出 --> [ 1, 2, 3]
@Value("#{ new int[]{1,2,3} }")
private int[] inlineArray;
3.5. list 列表
具体用法如下:
1. 通过索引获取List的值
2. 注入初始化List对象
// 通过List获取列表的第三个对象的country值: 输出 -->country_list_2
@Value("#{ inventor.placeOfBirthList[1].country}")
private String listIndexMember;
// 注入初始化List对象. {}表示空List : 输出 --> [ 1, 2, 3, 4]
@Value("#{ {1,2,3,4} }")
private List<Integer> inlineList;
// --
3.6. maps
具体用法如下:
1. 获取map的值
2. 注入初始化map对象
// 获取inventor对象的成员变量map的mapKey_2的值: 输出 --> 2
@Value("#{ inventor.map[mapKey_2]}")
private int mapKeyValue;
// 注入初始化map对象. {}表示空map: 输出 --> {"name": "hry","sex": "man"}
@Value("#{ {name:'hry',sex:'man'} }")
private Map<String,String> inlineMap;
3.7. Method invocation: 方法调用
具体用法如下:
- 调用string的方法
- 调用自定义对象的方法
// 调用string的方法: 输出 --> c
@Value("#{ 'abc'.substring(2, 3) }")
private String methodInvoke;
// 调用自定义对象的方法: 输出 --> false
@Value("#{ inventor.nameIsSame('name_1') }")
private String myObjectmethodInvoke;
// --
3.8. Relational operators(关系操作符)
具体用法如下:
- equal: (==)
- not equal
- less than:(<)
- less than or equal:(<=)
- greater than: (>)
- greater than or equal: (>=)
// 相同判断: 输出 --> true
@Value("#{ 2 == 2 }")
private boolean relationEqual;
// 大小比较: 输出 --> false
@Value("#{ 2 < -5.0 }")
private boolean relationLessThan;
3.9. Logical operators(逻辑操作符)
具体用法如下:
- and
- or
- not (!).
// and操作符: 输出 --> false
@Value("#{ true and false }")
private boolean logicalAnd;
// or操作符: 输出 --> true
@Value("#{ inventor.nameIsSame('name_1') or inventor.nameIsSame('name') }")
private boolean logicalOr;
// not操作符: 输出 --> false
@Value("#{ !true }")
private boolean logicalNot;
3.10. Mathematical operators:数学运算符
具体用法如下:
- Addition
- Subtraction
- multiplication
- division: (/)
- modulus: (%)
- exponential power: (^)
// : 输出 --> 2
@Value("#{ 1 + 1 }")
private int mathematicalAddition;
// 加法: 输出 --> 4
@Value("#{ 1 - -3 }")
private int mathematicalSubtraction;
// 减法: 输出 --> 6
@Value("#{ -2 * -3 }")
private int mathematicalMultiplication;
// 除法: 输出 --> -2
@Value("#{ 6 / -3 }")
private int mathematicalDivision;
// 取余: 输出 --> 1
@Value("#{ 8 / 5 % 2 }")
private int mathematicalModulus;
// 指数幂: 输出 --> 8
@Value("#{ 2 ^ 3 }")
private int mathematicalExponentialPower;
3.11. Ternary operator(三元运算符)
// 三元运算符: 输出 --> falseExp
@Value("#{false ? 'trueExp' : 'falseExp'}")
private String ternary;
3.12. Safe Navigation operator
如果获取的值没有,则通过?设置默认值
// 如果systemProperties['pop3.port']没有值,通过?指定默认值,避免抛出NullPointerException: 输出 --> 25
@Value("#{ systemProperties['pop3.port'] ?: 25 }")
private String safeNavigation;
3.13. Collection
具体用法如下:
1. Collection selection(集合选择): 语法.?[selectionExpression]
2. Collection projection(集合投影):语法
// 获取集合中对象placeOfBirth的city等于city_list_2的对象的集合: 输出 --> [{"city": "city_list_2", "country": "country_list_2"}]
@Value("#{ inventor.placeOfBirthList.?[city=='city_list_2'] }")
private List<PlaceOfBirth> collectionListSelection;
// 获取对象Invertor中map的value<2的对象,并生成新的map: 输出 --> {"mapKey_1": "1"}
@Value("#{ inventor.map.?[value<2] }")
private Map<String, String> collectionMapSelection;
// 获取inventor.placeOfBirthList的所有的属性city的值,并组成一个对象: 输出 --> "collectionProjection": ["city_list_1","city_list_2", "city_list_3"]
@Value("#{ inventor.placeOfBirthList.![city] }")
private List<String> collectionProjection;
4. 相关的代码
4.1. 完整代码
见Github