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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM