EvaluationContext是一个用于评估表达式的接口,它能解析属性、方法和字段,并且帮助执行类型转换。它在表达式的解析和执行过程中扮演着重要的角色,是一个非常有用的工具。
当使用StandardEvaluationContext时,我们可以直接调用相关方法来解析属性、调用方法和访问字段。此外,它还提供了类型转换的功能,可以帮助我们处理不同类型之间的转换。
在具体的实现中,标准实现StandardEvaluationContext使用反射来操作对象,并且它缓存了java.lang.reflect的方法、字段和构造函数实例,以提升性能。这种实现方式充分利用了Java的反射机制,使得对象操作过程更加高效。
EvaluationContext和其标准实现StandardEvaluationContext是进行表达式评估和执行的重要工具,通过反射机制和缓存功能来提升性能,并简化对象操作和类型转换的过程。
在StandardEvaluationContext中,您可以使用setRootObject()方法或在构造函数中传入根对象来指定要评估的对象。此外,您还可以使用setVariable()和registerFunction()方法来指定在表达式中使用的变量和函数。
如果需要扩展SpEL评估表达式的功能,您还可以在StandardEvaluationContext中注册自定义的ConstructorResolvers、MethodResolvers和PropertyAccessors。
SpEL默认使用Spring Core中的ConversionService进行类型转换。该转换服务内置了许多常用的转换器,并且还支持完全的可扩展性,因此您可以添加自定义的类型转换器。此外,该转换服务还具有泛型感知的重要功能。这意味着当在表达式中使用泛型类型时,SpEL会自动尝试进行转换,以保持对象的类型正确性。
在实践中,这意味着当使用SpEL的setValue()方法进行赋值时,如果要设置的属性是一个List类型,而实际上该属性的具体类型是List,SpEL会自动识别出在将元素放入列表之前需要将其转换为布尔值。下面是一个简单的例子:
class Simple {
public List<Boolean> booleanList = new ArrayList<Boolean>();
}
Simple simple = new Simple();
simple.booleanList.add(true);
StandardEvaluationContext simpleContext = new StandardEvaluationContext(simple);
// false is passed in here as a string. SpEL and the conversion service will
// correctly recognize that it needs to be a Boolean and convert it
parser.parseExpression("booleanList[0]").setValue(simpleContext, "false");
// b will be false
Boolean b = simple.booleanList.get(0);
SpEL表达式可以与基于XML或注解的配置元数据一起使用,用于定义BeanDefinition。无论是在XML配置还是注解配置中,定义表达式的语法形式都是#{<表达式字符串>}
。
在XML配置中,可以使用SpEL表达式来定义bean的属性值、方法参数值甚至构造函数参数值。例如:
<bean id="myBean" class="com.example.MyBean">
<property name="name" value="#{user.name}" />
<property name="age" value="#{user.age + 1}" />
<constructor-arg value="#{user.address}" />
<property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>
bean>
在上面的示例中,我们使用SpEL表达式来引用另一个bean中的属性值,并进行一些计算。user.name
表示引用名为user
的bean中的name
属性值,user.age + 1
表示引用user
的age
属性值并在其基础上加1,user.address
表示引用user
的address
属性值作为构造函数参数值。
在Spring表达式语言(SpEL)中,systemProperties
是一个预定义的对象,用于访问系统属性。系统属性是指Java虚拟机(JVM)运行时设置的属性,可以通过System.getProperty(String key)
方法来获取。
使用systemProperties
对象,可以在SpEL表达式中获取和操作系统属性。例如,可以使用systemProperties['java.version']
来获取Java版本的系统属性,或者使用systemProperties['user.dir']
来获取当前工作目录的系统属性。
以下是一个示例,展示了如何在SpEL表达式中使用systemProperties
对象:
<bean id="testBean" class="xxxx.TestBean">
<property name="userRegion" value="#{ systemProperties['user.region'] }"/>
bean>
在注解配置中,可以使用SpEL表达式来定义注解中的属性值。例如:
@Component
public class TestBean{
@Value("#{user.region}")
private String region;
// ...
}
在上面的示例中,我们使用SpEL表达式作为@Value
注解的属性值,来引用另一个bean中的属性值并进行一些计算。#{user.region}
表示引用名为user
的bean中的region
属性值。
通过使用SpEL表达式,我们可以灵活地在配置中引用和计算属性值,使配置更加动态和可配置化。
@Value("#{systemProperties['user.name']}")
private String username;
@Value("#{systemProperties['os.name']}")
private String osName;
在上述示例中,我们使用@Value
注解将系统属性赋值给Java类中的两个变量:username
和osName
。systemProperties['user.name']
将获取当前用户的用户名,而systemProperties['os.name']
将获取当前操作系统的名称。
需要注意的是,systemProperties
对象只能访问系统属性,而不能访问环境变量。如果需要访问环境变量,可以使用systemEnvironment
对象。
例如,还可以通过名称来引用其他bean的属性。
<bean id="numberGuess" class="org.spring.samples.NumberGuess">
<property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>
bean>
<bean id="shapeGuess" class="org.spring.samples.ShapeGuess">
<property name="initialShapeSeed" value="#{numberGuess.randomNumber}"/>
bean>
自动装配(Autowiring)方法和构造函数
@Autowired
public TestBean( @Value("#{systemProperties['user.region']}"} String defaultLocale) {
this.defaultLocale = defaultLocale;
}
$
和#
符号有不同的用途和含义:$
符号:$
符号用于引用直接访问的变量或属性。它表示直接获取当前上下文中的值,例如 ${name}
表示获取名为 name
的变量的值。$
符号通常在XML属性配置中使用。
#
符号:#
符号用于引用通过Spring容器管理的bean。它表示获取由Spring容器创建和管理的bean的引用,可以调用bean的方法和访问bean的属性。例如 #{person.getName()}
表示获取名为 person
的bean的getName()
方法的返回值。#
符号通常在注解或SpEL表达式中使用。
总的来说,$
符号用于引用直接访问的变量或属性,而#
符号用于引用通过Spring容器管理的bean。它们在不同的上下文中使用,具有不同的含义和作用。