专栏名称: hryou0922
目录
相关文章推荐
上海证券报  ·  朱芝松被查 ·  昨天  
国泰君安证券研究  ·  国君基金研究|熨平红利周期波动的稳健选股策略 ·  1 周前  
51好读  ›  专栏  ›  hryou0922

Spring SpEL系列一 基础用法

hryou0922  · 掘金  ·  · 2018-01-22 02:31

正文

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(文字表达式)

子类又细分为以下类别:

  1. strings
  2. numeric
  3. boolean
  4. 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: 方法调用

具体用法如下:

  1. 调用string的方法
  2. 调用自定义对象的方法
// 调用string的方法: 输出 --> c
@Value("#{ 'abc'.substring(2, 3) }")
private String methodInvoke;

// 调用自定义对象的方法: 输出 --> false
@Value("#{ inventor.nameIsSame('name_1') }")
private String myObjectmethodInvoke;


// --

3.8. Relational operators(关系操作符)

具体用法如下:

  1. equal: (==)
  2. not equal
  3. less than:(<)
  4. less than or equal:(<=)
  5. greater than: (>)
  6. greater than or equal: (>=)
// 相同判断: 输出 --> true
@Value("#{ 2 == 2 }") 
private boolean relationEqual;

// 大小比较: 输出 --> false
@Value("#{ 2 < -5.0 }")
private boolean relationLessThan;

3.9. Logical operators(逻辑操作符)

具体用法如下:

  1. and
  2. or
  3. 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:数学运算符

具体用法如下:

  1. Addition
  2. Subtraction
  3. multiplication
  4. division: (/)
  5. modulus: (%)
  6. 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