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

本文轉自:https://blog.csdn.net/yinwenjie/article/details/78155548

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切面配置)

<==== 上一篇  =====>

Spring/Boot/Cloud系列知識(4)— — 代理模式(下)

<==== 下一篇  =====>

Spring/Boot/Cloud系列知識(6)— — Spring EL(2)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章