✒️ 作者 - Lex 📝 博客 - 掘金 📚 源码地址 - github
Spring 表达式语言(SpEL)
对象属性访问与反射机制
设计模式
PropertyAccessor
接口时可能会用到。PropertyAccessor
接口的作用在于定义了一套统一的属性访问规范,通过该接口可以实现对对象属性的读取和写入操作,使得 Spring 框架中的各个模块能够统一地访问对象的属性,从而实现更加灵活和可扩展的应用开发。通过实现这个接口,可以定制化对象属性的访问逻辑,以满足不同场景下的需求,例如在 Spring 表达式语言(SpEL)、数据绑定、AOP 编程等方面发挥作用。
属性读取
canRead()
方法用于判断是否可以读取指定属性,以及 read()
方法用于读取属性的值。这使得可以通过统一的方式从对象中获取属性值。属性写入
canWrite()
方法用于判断是否可以写入指定属性,以及 write()
方法用于设置属性的值。这使得可以通过统一的方式向对象中设置属性值。自定义属性访问逻辑
PropertyAccessor
实现类来访问对象的属性,从而实现特定的业务逻辑或行为。适配不同的对象结构
PropertyAccessor
实现类,以适应不同类型的对象,包括 JavaBean、Map、数组等。PropertyAccessor
的接口,它用于读取和写入对象的属性。接口中包含了四个方法,分别用于判断是否能够读取属性、读取属性值、判断是否能够写入属性以及写入属性值。此外,接口中还包含了一个用于获取特定目标类数组的方法。该接口提供了一种统一的方式来访问对象的属性,使得可以实现自定义的属性访问逻辑,并能够适配不同的对象结构。
/**
* 属性访问器能够读取(可能写入)对象的属性。
*
* <p>这个接口没有限制,因此实现者可以自由地直接访问属性作为字段,或通过getter方法或其他方式访问属性。
*
* <p>解析器可以选择指定一个目标类的数组,用于调用它。然而,如果从{@link #getSpecificTargetClasses()}返回{@code null},它将被调用
* 以尝试解析所有属性引用,并有机会确定它是否可以读取或写入它们。
*
* <p>属性解析器被认为是有序的,并且每个都将依次被调用。影响调用顺序的唯一规则是,在{@link #getSpecificTargetClasses()}中直接命名目标类的任何解析器
* 将在通用解析器之前首先被调用。
*
* @author Andy Clement
* @since 3.0
*/
public interface PropertyAccessor {
/**
* 返回此解析器应该被调用的类数组。
* <p>返回{@code null}表示这是一个通用解析器,可以在任何类型上尝试解析属性。
* @return 适用于此解析器的类数组(或{@code null}如果是通用解析器)
*/
@Nullable
Class<?>[] getSpecificTargetClasses();
/**
* 用于确定解析器实例是否能够访问指定目标对象上的指定属性。
* @param context 尝试进行访问的评估上下文
* @param target 要访问属性的目标对象
* @param name 要访问的属性的名称
* @return 如果此解析器能够读取属性,则为true
* @throws AccessException 如果有任何问题确定是否可以读取属性
*/
boolean canRead(EvaluationContext context, @Nullable Object target, String name) throws AccessException;
/**
* 用于从指定的目标对象中读取属性。
* 只有当{@link #canRead}也返回{@code true}时才能成功。
* @param context 尝试进行访问的评估上下文
* @param target 要访问属性的目标对象
* @param name 要访问的属性的名称
* @return 包装读取的属性值和其类型描述符的TypedValue对象
* @throws AccessException 如果有任何问题访问属性值
*/
TypedValue read(EvaluationContext context, @Nullable Object target, String name) throws AccessException;
/**
* 用于确定解析器实例是否能够向指定目标对象上的指定属性写入。
* @param context 尝试进行访问的评估上下文
* @param target 要访问属性的目标对象
* @param name 要访问的属性的名称
* @return 如果此解析器能够写入属性,则为true
* @throws AccessException 如果有任何问题确定是否可以写入属性
*/
boolean canWrite(EvaluationContext context, @Nullable Object target, String name) throws AccessException;
/**
* 用于向指定目标对象的属性写入。
* 只有当{@link #canWrite}也返回{@code true}时才能成功。
* @param context 尝试进行访问的评估上下文
* @param target 要访问属性的目标对象
* @param name 要访问的属性的名称
* @param newValue 属性的新值
* @throws AccessException 如果有任何问题写入属性值
*/
void write(EvaluationContext context, @Nullable Object target, String name, @Nullable Object newValue)
throws AccessException;
}
BeanExpressionContextAccessor
BeanExpressionContextAccessor
,可以在 SpEL 表达式中直接访问上下文中的对象属性,这在某些场景下非常有用,例如在 Spring 的 @Value
注解中使用 SpEL 表达式读取配置属性。BeanFactoryAccessor
BeanFactory
中注册的 Bean 对象的属性。BeanFactory
是 Spring IoC 容器的核心接口,用于管理和创建 Bean。通过 BeanFactoryAccessor
,可以在 SpEL 表达式中访问 IoC 容器中注册的 Bean,读取和设置其属性值,这为在 SpEL 中访问 Spring Bean 提供了便利。CompilablePropertyAccessor
DataBindingPropertyAccessor
DataBindingPropertyAccessor
提供了方便的方式来读取和设置对象的属性值,用于处理数据绑定过程中的属性访问需求。EnvironmentAccessor
EnvironmentAccessor
用于从 Spring 环境中访问属性,例如读取配置文件中的属性值。Spring 的环境抽象提供了一种统一的方式来访问应用程序的环境属性,包括系统属性、环境变量、配置文件等。通过 EnvironmentAccessor
,可以在 SpEL 表达式中直接访问 Spring 环境中的属性值,从而实现动态的配置和属性注入。JspPropertyAccessor
eval
标签)内访问对象的属性,可以实现更加灵活和可配置的页面逻辑。MapAccessor
MapAccessor
用于在 SpEL 表达式中直接访问 Map 对象中的键值对。Map 是一种常见的数据结构,用于存储键值对的集合。通过 MapAccessor
,可以在 SpEL 表达式中直接访问 Map 对象中的键值对,读取和设置其属性值,这为在 SpEL 中操作 Map 提供了便利。OptimalPropertyAccessor
OptimalPropertyAccessor
提供了属性访问的优化实现,通常在 ReflectivePropertyAccessor
内部使用,用于提高属性访问的性能。通过对属性访问逻辑的优化,可以减少不必要的计算和提高执行效率,从而更加高效地访问对象的属性值。创建了一个 SpEL 表达式解析器对象 ExpressionParser
,然后创建了一个 StandardEvaluationContext
对象作为 SpEL 表达式的上下文。在上下文中设置了一个名为 myBean
的变量,其值为一个 MyBean
对象。接着,通过 parser.parseExpression("#myBean.name")
解析了一个 SpEL 表达式,该表达式表示访问 myBean
对象的 name
属性。最后,通过 getValue(context, String.class)
方法获取了属性值,并将其输出。
public class PropertyAccessorDemo {
public static void main(String[] args) {
// 创建一个SpEL表达式解析器
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("myBean",new MyBean("spring-reading"));
// 解析SpEL表达式,并使用构造函数实例化对象
String name = parser.parseExpression("#myBean.name").getValue(context, String.class);
System.out.println("name = " + name);
}
}
MyBean
类定义了一个简单的 Java Bean,具有一个名为 name
的私有字段和相应的 getter 和 setter 方法。
public class MyBean {
private String name;
public MyBean(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "MyBean{" +
"name='" + name + '\'' +
'}';
}
}
运行结果,通过 SpEL 表达式解析器访问了对象的属性,并得到了属性值 "spring-reading"。
name = spring-reading
Spring 表达式语言(SpEL)
PropertyAccessor
接口被用于访问对象的属性。SpEL 提供了一种在运行时动态求值表达式的机制,通过 PropertyAccessor
接口可以实现对对象属性的读写操作。Spring 数据绑定
PropertyAccessor
接口提供了一种统一的方式来访问对象的属性,可以在数据绑定过程中使用。Spring AOP 编程
PropertyAccessor
接口可以用于访问被增强对象的属性。通过 AOP 可以实现对被增强对象的属性进行拦截、修改等操作。Spring IOC 容器
PropertyAccessor
接口可以用于访问注册在容器中的 Bean 对象的属性。通过 IoC 容器,可以方便地管理和访问对象的属性。其他自定义组件
PropertyAccessor
接口还可以被自定义组件使用。例如,在自定义的框架或库中,可以使用 PropertyAccessor
接口来实现对对象属性的访问操作,以实现特定的功能或逻辑。属性访问权限问题
PropertyAccessor
接口时,可能会遇到对象的属性访问权限不足的问题,导致无法读取或写入属性。这可能涉及到对象的访问控制和权限设置。属性命名问题
属性类型转换问题
上下文环境配置问题
PropertyAccessor
接口时,需要提供一个合适的上下文环境(如 EvaluationContext
),可能会出现配置错误或环境设置不当的问题,导致属性访问失败。异常处理问题
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。