百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

SpEL使用详解

toyiye 2024-06-21 12:27 9 浏览 0 评论

SpEL全称Spring Expression Language,是一种强大的表达式语言,支持在运行时查询和操纵对象图。在SpEL诞生以前就已经有多种表达式语言了,如OGNL,MVEL,JBoss EL等等,那么Spring团队为什么还要发明SpEL呢?SpEL的目标是对Spring所有作品集提供良好的表达式计算支持。另外SpEL虽然对Spring的项目集提供良好的支持,但并不依赖于Spring运行,SpEL可以独立运行。

使用

在Spring中使用SpEL只需要编写SpEL表达式字符串就可以了,因为Spring已经为我们集成好了SpEL,如果是单独使用SpEL需要编写一些启动SpEL的代码,然后才能进行表达式计算,启动类代码中主要使用ExpressionParser,SpelExpressionParser,EvaluationContext,SimpleEvaluationContext,StandardEvaluationContext几个类,作为模板代码,以下如果不特殊说明,所有的表达式计算均在该模板代码中进行计算,其中parser就是指SpelExpressionParser,而context是SimpleEvaluationContext或者StandardEvaluationContext。

1
2
3
4
5
6
7
8
9
ExpressionParser parser = new SpelExpressionParser();
Inventor inventor = new Inventor("tesla", new Date(), "Serbian");
inventor.setPlaceOfBirth(new PlaceOfBirth("AAA", "CCC"));
//EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().withRootObject(inventor).build();
StandardEvaluationContext context = new StandardEvaluationContext(inventor);
int year = (Integer) parser.parseExpression("Birthdate.Year + 1900").getValue(context);
System.out.println(year);
String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context);
System.out.println(city);

例子中使用的类如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package org.spring.samples.spel.inventor;

import java.util.Date;
import java.util.GregorianCalendar;

public class Inventor {

    private String name;
    private String nationality;
    private String[] inventions;
    private Date birthdate;
    private PlaceOfBirth placeOfBirth;

    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;
    }

    public Inventor() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNationality() {
        return nationality;
    }

    public void setNationality(String nationality) {
        this.nationality = nationality;
    }

    public Date getBirthdate() {
        return birthdate;
    }

    public void setBirthdate(Date birthdate) {
        this.birthdate = birthdate;
    }

    public PlaceOfBirth getPlaceOfBirth() {
        return placeOfBirth;
    }

    public void setPlaceOfBirth(PlaceOfBirth placeOfBirth) {
        this.placeOfBirth = placeOfBirth;
    }

    public void setInventions(String[] inventions) {
        this.inventions = inventions;
    }

    public String[] getInventions() {
        return inventions;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package org.spring.samples.spel.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;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String s) {
        this.city = s;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package org.spring.samples.spel.inventor;

import java.util.*;

public class Society {

    private String name;

    public static String Advisors = "advisors";
    public static String President = "president";

    private List<Inventor> members = new ArrayList<Inventor>();
    private Map officers = new HashMap();

    public List getMembers() {
        return members;
    }

    public Map getOfficers() {
        return officers;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isMember(String name) {
        for (Inventor inventor : members) {
            if (inventor.getName().equals(name)) {
                return true;
            }
        }
        return false;
    }
}

SpEL语法

字面量表达式

spel字面量表达式支持字符串,数字(整数,实数,16进制数),布尔,以及null。字符串使用单引号包裹。如果字符串中包含单引号',那么单引号需要使用两个单引号''来转义。

1
2
3
4
5
6
7
8
9
10
11
12
13
ExpressionParser parser = new SpelExpressionParser();

// evals to "Hello World"
String helloWorld = (String) parser.parseExpression("'Hello World'").getValue();

double avogadrosNumber = (Double) parser.parseExpression("6.0221415E+23").getValue();

// evals to 2147483647
int maxValue = (Integer) parser.parseExpression("0x7FFFFFFF").getValue();

boolean trueValue = (Boolean) parser.parseExpression("true").getValue();

Object nullValue = parser.parseExpression("null").getValue();

属性、数组、列表、Maps和索引表达式

属性导航语法使用.,支持多级导航。

下面例子中使用的context的根对象为Inventor对象,在测试时需要自己new一个对象,并设置为context的根对象。

注意属性的首字母是不区分大小写的

1
2
3
4
// evals to 1856
int year = (Integer) parser.parseExpression("Birthdate.Year + 1900").getValue(context);

String city = (String) parser.parseExpression("placeOfBirth.City").getValue(context);

数组和列表的元素使用方括号[]记法访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

// Inventions Array

// evaluates to "Induction motor"
String invention = parser.parseExpression("inventions[3]").getValue(
        context, tesla, String.class);

// Members List

// evaluates to "Nikola Tesla"
String name = parser.parseExpression("Members[0].Name").getValue(
        context, ieee, String.class);

// List and Array navigation
// evaluates to "Wireless communication"
String invention = parser.parseExpression("Members[0].Inventions[6]").getValue(
        context, ieee, String.class);

Maps的条目检索也使用[]记法,不同于数组和列表的索引,这里的索引是字符串

1
2
3
4
5
6
7
8
9
10
11
12
// Officer's Dictionary

Inventor pupin = parser.parseExpression("Officers['president']").getValue(
        societyContext, Inventor.class);

// evaluates to "Idvor"
String city = parser.parseExpression("Officers['president'].PlaceOfBirth.City").getValue(
        societyContext, String.class);

// setting values
parser.parseExpression("Officers['advisors'][0].PlaceOfBirth.Country").setValue(
        societyContext, "Croatia");

内联列表达式

spel可以使用{}表示列表字面量

{}本身表示空列表

1
2
3
4
// evaluates to a Java list containing the four numbers
List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue(context);

List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue(context);

内联Maps表达式

spel中可以使用{:}记法表示Map字面量

{:}本身表示空Map

1
2
3
4
// evaluates to a Java map containing the two entries
Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue(context);

Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue(context);

创建数组表达式

spel中可以使用熟悉的java语法创建数组,并且可以提供初始化器在创建时填充数组。当前spel还不支持多维数组的初始化器。

1
2
3
4
5
6
7
int[] numbers1 = (int[]) parser.parseExpression("new int[4]").getValue(context);

// Array with initializer
int[] numbers2 = (int[]) parser.parseExpression("new int[]{1,2,3}").getValue(context);

// Multi dimensional array
int[][] numbers3 = (int[][]) parser.parseExpression("new int[4][5]").getValue(context);

方法调用表达式

spel中可以使用java的语法调用方法。可以调用字面量的方法。支持变量参数。

1
2
3
4
5
6
// string literal, evaluates to "bc"
String bc = parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class);

// evaluates to true
boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(
        societyContext, Boolean.class);

运算符表达式

spel支持4种运算符,分别是关系运算符,逻辑运算符,算术运算符,赋值运算符。这些运算符和java中的运算符一致,只是有些运算符提供了别名。

关系运算符包括等于、不等于、小于、小于等于、大于、大于等于。

关系运算符

1
2
3
4
5
6
7
8
// evaluates to true
boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);

// evaluates to false
boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);

// evaluates to true
boolean trueValue = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);

除了标准的关系运算符外,spel还支持instanceof和基于正则表达式匹配语法matches

1
2
3
4
5
6
7
8
9
10
11
// evaluates to false
boolean falseValue = parser.parseExpression(
        "'xyz' instanceof T(Integer)").getValue(Boolean.class);

// evaluates to true
boolean trueValue = parser.parseExpression(
        "'5.00' matches '^-?\\d+(\\.\\d{2})?#39;").getValue(Boolean.class);

//evaluates to false
boolean falseValue = parser.parseExpression(
        "'5.0067' matches '^-?\\d+(\\.\\d{2})?#39;").getValue(Boolean.class);

值得注意的是spel表达式中在计算时原始类型会立即转化成包裹器类型,所以1 instanceof T(int)计算结果为false,而1 instanceof T(Integer)计算结果为true

有时候spel表达式会内嵌到文档中去,如xml文档,而在这些文档中,运算符符号会有特殊的含义,为了避免产生问题,有些运算符符号会有一个对应的文本表示。并且文本表示是大小写不敏感的。

  • lt (<)
  • gt (>)
  • le (<=)
  • ge (>=)
  • eq (==)
  • ne (!=)
  • div (/)
  • mod (%)
  • not (!)

逻辑运算符

spel支持3种逻辑运算符

  • and (&&)
  • or (||)
  • not (!)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// -- AND --

// evaluates to false
boolean falseValue = parser.parseExpression("true and false").getValue(Boolean.class);

// evaluates to true
String expression = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')";
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);

// -- OR --

// evaluates to true
boolean trueValue = parser.parseExpression("true or false").getValue(Boolean.class);

// evaluates to true
String expression = "isMember('Nikola Tesla') or isMember('Albert Einstein')";
boolean trueValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);

// -- NOT --

// evaluates to false
boolean falseValue = parser.parseExpression("!true").getValue(Boolean.class);

// -- AND and NOT --
String expression = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";
boolean falseValue = parser.parseExpression(expression).getValue(societyContext, Boolean.class);

算术运算符

spel中加法运算可以作用到数字和字符串的运算,而减、乘、除只能作用到数字上。求模运算和指数运算也只能作用到数字上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Addition
int two = parser.parseExpression("1 + 1").getValue(Integer.class);  // 2

String testString = parser.parseExpression(
        "'test' + ' ' + 'string'").getValue(String.class);  // 'test string'

// Subtraction
int four = parser.parseExpression("1 - -3").getValue(Integer.class);  // 4

double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class);  // -9000

// Multiplication
int six = parser.parseExpression("-2 * -3").getValue(Integer.class);  // 6

double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class);  // 24.0

// Division
int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class);  // -2

double one = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class);  // 1.0

// Modulus
int three = parser.parseExpression("7 % 4").getValue(Integer.class);  // 3

int one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class);  // 1

// Operator precedence
int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class);  // -21

赋值运算符

spel中可以为属性赋值,有两种方式,一种是使用赋值运算符配合getValue方法调用,另外一种是直接通过setValue方法调用。

1
2
3
4
5
6
7
8
Inventor inventor = new Inventor();
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();

parser.parseExpression("Name").setValue(context, inventor, "Aleksandar Seovic");

// alternatively
String aleks = parser.parseExpression(
        "Name = 'Aleksandar Seovic'").getValue(context, inventor, String.class);

类型表达式

在spel中可以使用T运算符指定一个java.lang.Class类型的实例。静态方法调用也使用该运算符。指定类型时除了java.lang包中的类可以使用简单名称外,其余类均需要使用全限定名。

1
2
3
4
5
6
7
Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);

Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);

boolean trueValue = parser.parseExpression(
        "T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR")
        .getValue(Boolean.class);

构造器调用表达式

使用java标准的new语法调用构造器创建一个类的实例,注意类名称需要使用全限定名。

1
2
3
4
5
6
7
8
Inventor einstein = p.parseExpression(
        "new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')")
        .getValue(Inventor.class);

//create new inventor instance within add method of List
p.parseExpression(
        "Members.add(new org.spring.samples.spel.inventor.Inventor(
            'Albert Einstein', 'German'))").getValue(societyContext);

变量

变量是通过EvaluationContext接口的setVariable方法调用创建的,在表达式中可以使用#variableName语法引用变量。

变量名称只能是下列一个或多个字符的组合

  • 字母a-z以及A-Z
  • 数字0-9
  • 下划线_
  • 美元符号$
1
2
3
4
5
6
7
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");

EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
context.setVariable("newName", "Mike Tesla");

parser.parseExpression("Name = #newName").getValue(context, tesla);
System.out.println(tesla.getName())  // "Mike Tesla"

特殊的#this和#root变量

#this变量在每一步计算时总是有定义的,并且值为当前计算对象。#root变量也总是有定义的,表示根对象。也就是说#this在每一步计算表达式时都可能会发生变化,而#root总是表示根对象。

下面的例子中使用了集合筛选语法.?[筛选表达式],如果看不明白可以先阅读集合筛选

1
2
3
4
5
6
7
8
9
10
11
12
13
// create an array of integers
List<Integer> primes = new ArrayList<Integer>();
primes.addAll(Arrays.asList(2,3,5,7,11,13,17));

// create parser and set variable 'primes' as the array of integers
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataAccess();
context.setVariable("primes", primes);

// all prime numbers > 10 from the list (using selection ?{...})
// evaluates to [11, 13, 17]
List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression(
        "#primes.?[#this>10]").getValue(context);

函数

可以通过EvaluationContext的setVariable方法调用来创建自定义函数,然后在spel表达式中通过变量引用语法类似的方式调用自定义函数

1
2
3
4
Method method = ...;

EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
context.setVariable("myFunction", method);

下面创建一个工具方法来把一个字符串逆序产生一个新的字符串。

1
2
3
4
5
6
7
8
9
10
public abstract class StringUtils {

    public static String reverseString(String input) {
        StringBuilder backwards = new StringBuilder(input.length());
        for (int i = 0; i < input.length(); i++) {
            backwards.append(input.charAt(input.length() - 1 - i));
        }
        return backwards.toString();
    }
}

一个完整的函数注册和使用的例子

1
2
3
4
5
6
7
8
ExpressionParser parser = new SpelExpressionParser();

EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
context.setVariable("reverseString",
        StringUtils.class.getDeclaredMethod("reverseString", String.class));

String helloWorldReversed = parser.parseExpression(
        "#reverseString('hello')").getValue(context, String.class);

Bean引用

如果计算上下文EvaluationContext已经配置了一个bean解析器,可以在spel表达式中使用@beanName语法来查找bean

1
2
3
4
5
6
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());

// This will end up calling resolve(context,"something") on MyBeanResolver during evaluation
Object bean = parser.parseExpression("@something").getValue(context);

如果是访问bean对应的factory bean,可以使用&beanName语法。

1
2
3
4
5
6
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());

// This will end up calling resolve(context,"&foo") on MyBeanResolver during evaluation
Object bean = parser.parseExpression("&foo").getValue(context);

三元运算符

可以使用三元运算符在表达式中执行if-then-else的条件判断逻辑。

语法为java标准的三元运算符? :

1
2
String falseString = parser.parseExpression(
        "false ? 'trueExp' : 'falseExp'").getValue(String.class);

执行结果为'falseExp'

下面是一个更为现实的例子

1
2
3
4
5
6
7
8
9
parser.parseExpression("Name").setValue(societyContext, "IEEE");
societyContext.setVariable("queryName", "Nikola Tesla");

expression = "isMember(#queryName)? #queryName + ' is a member of the ' " +
        "+ Name + ' Society' : #queryName + ' is not a member of the ' + Name + ' Society'";

String queryResultString = parser.parseExpression(expression)
        .getValue(societyContext, String.class);
// queryResultString = "Nikola Tesla is a member of the IEEE Society"

Elvis运算符

Elvis运算符借鉴于groovy语言,是java三元运算符的简写形式。通常在使用三元运算符时,一个变量要重复两次,如下面所示

1
2
String name = "Elvis Presley";
String displayName = (name != null ? name : "Unknown");

为了简化这种情形,可以使用Elvis运算符来简写

1
2
3
4
ExpressionParser parser = new SpelExpressionParser();

String name = parser.parseExpression("name?:'Unknown'").getValue(new Inventor(), String.class);
System.out.println(name);  // 'Unknown'

可以使用Elvis运算符为spel表达式提供缺省值,下面是一个在@value注解中使用Elvis运算符的例子

1
@Value("#{systemProperties['pop3.port'] ?: 25}")

上面的例子中将会注入一个系统属性pop3.port,如果没有定义将会使用25

安全导航运算符

安全导航运算符也是借鉴于groovy语言,是为了避免在访问一个对象的属性时,产生空指针异常。使用安全导航在访问属性所属的对象为null时,会返回null而不会产生NullPointerException

1
2
3
4
5
6
7
8
9
10
11
12
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));

String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
System.out.println(city);  // Smiljan

tesla.setPlaceOfBirth(null);
city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
System.out.println(city);  // null - does not throw NullPointerException!!!

集合筛选

集合筛选用于筛选原始集合中符合条件的元素,产生一个原始集合的子集合。

语法为.?[筛选表达式]

1
2
List<Inventor> list = (List<Inventor>) parser.parseExpression(
        "Members.?[Nationality == 'Serbian']").getValue(societyContext);

集合筛选可以应用于List和Map。对于List,筛选条件的当前计算对象是List中的每一个元素;而对于Map,筛选条件的当前计算对象是Map的条目,类型为Map.Entry,每一个条目的key和value属性可以在筛选表达式中访问。

1
Map newMap = parser.parseExpression("map.?[value<27]").getValue();

除了返回所有符合条件的元素外,还可以检索第一个或者最后一个符合条件的元素。

获取第一个符合筛选表达式的元素的语法是.^[筛选表达式]

获取最后一个符合条件的元素的语法是.$[筛选表达式]

集合投影

集合投影或者叫做集合映射,是通过原始集合上计算投影表达式,将原始集合中的每一个元素产生一个新的元素,新的元素可能与原始集合中的元素类型相同,也可能不同。

集合投影的语法为.![投影表达式]

下面的例子中获取所有Inventor的出生城市,原始集合为List<Inventor>,而投影后的集合为List<String>

1
2
// returns ['Smiljan', 'Idvor' ]
List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]");

也可以对Map进行集合投影,投影表达式的计算上下文对应为Map中的每一个条目,类型为Map.Entry,投影的结果是一个List。

表达式模板

表达式模板允许在spel表达式中混合字面量文本和一个或多个计算块,计算块是由我们定义的前缀和后缀字符串包裹的spel表达式。通常使用默认常用的#{}作为计算块的包裹字符串。

1
2
3
4
5
String randomPhrase = parser.parseExpression(
        "random number is #{T(java.lang.Math).random()}",
        new TemplateParserContext()).getValue(String.class);

// evaluates to "random number is 0.7038186818312008"

类似于字符串内插,上面例子中的random number is 作为字面量文本和#{}中包裹的表达式计算结果相连接。

注意parseExpression方法的第二个参数是一个ParserContext接口类型的参数,该接口会影响表达式解析时对表达式模板的计算。

下面是TemplateParserContext的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TemplateParserContext implements ParserContext {

    public String getExpressionPrefix() {
        return "#{";
    }

    public String getExpressionSuffix() {
        return "}";
    }

    public boolean isTemplate() {
        return true;
    }
}

注意

  1. 由于SpEL表达式本身使用字符串表示,所以SpEL中字符串字面量使用’’(单引号)表示。
  2. SpEL中属性访问时,属性的首字母是不区分大小写的,也就是说属性name和Name表示同一个属性
  3. 在SpEL中访问变量时使用#var的形式,在Spring中所有ApplicationContext中定义的bean都是预定义的变量,变量名称为bean名称,包括标准的环境抽象environment(org.springframework.core.env.Environment)、jvm系统属性systemProperties(Map<String, Object>)、系统环境变量systemEnvironment(Map<String, Object>),但是在访问这些变量时不需要使用#var语法,只需要使用var就可以了

SpEL表达式在Bean定义中的应用

这里的bean定义使用java注解方式配置

SpEL表达式在bean定义中的应用主要是使用@Value注解的方式对bean的属性,方法,方法参数以及构造器参数进行依赖注入

为属性注入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
public class FieldValueTestBean {

    @Value("#{ systemProperties['user.region'] }")
    private String defaultLocale;

    public void setDefaultLocale(String defaultLocale) {
        this.defaultLocale = defaultLocale;
    }

    public String getDefaultLocale() {
        return this.defaultLocale;
    }
}

通过setter方法注入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
public class PropertyValueTestBean {

    private String defaultLocale;

    @Value("#{ systemProperties['user.region'] }")
    public void setDefaultLocale(String defaultLocale) {
        this.defaultLocale = defaultLocale;
    }

    public String getDefaultLocale() {
        return this.defaultLocale;
    }
}

在自动装配方法或构造器上注入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class SimpleMovieLister {

    private MovieFinder movieFinder;
    private String defaultLocale;

    @Autowired
    public void configure(MovieFinder movieFinder,
            @Value("#{ systemProperties['user.region'] }") String defaultLocale) {
        this.movieFinder = movieFinder;
        this.defaultLocale = defaultLocale;
    }

    // ...
}

public class MovieRecommender {

    private String defaultLocale;

    private CustomerPreferenceDao customerPreferenceDao;

    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao,
            @Value("#{systemProperties['user.country']}") String defaultLocale) {
        this.customerPreferenceDao = customerPreferenceDao;
        this.defaultLocale = defaultLocale;
    }

    // ...
}

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码