Spring源码如何修改Bean的属性用到的相关类
关于Spring在处理Bean给属性赋值,或者执行实例化好的Bean的某些方法时,用到了好几个类,下面看下这些都是怎么实现的
一、PropertyDescriptor
PropertyDescriptor类表示JavaBean类通过存储器导出一个属性,可以通过该类,完成对实例化好的Bean的某些方法调用
比如setxx或者getxxx,比如Spring在处理带有@Autowired注解修饰的方法时,就是通过这个来完成调用的
该类常用的方法有:
Method getReadMethod() //获得用于读取属性值的方法 Method getWriteMethod() //获得用于写入属性值的方法
PropertyDescriptor的案例
1、通过反射创建TaskProvidePropsList实例
2、通过PropertyDescriptor拿属性的set方法,修改属性的值
Class clazz = Class.forName("TaskProvidePropsList");//拿到类clazz对象
Object obj = clazz.newInstance();//实例化
Field[] fields = clazz.getDeclaredFields();//拿到这个对象的所有属性字段
//写数据
for (Field f : fields) {
//创建PropertyDescriptor对象,设置需要改动哪个类的哪个属性字段名
PropertyDescriptor pd = new PropertyDescriptor(f.getName(), clazz);
Method wM = pd.getWriteMethod();//获得该属性写方法
wM.invoke(obj, 2);//其实这里是执行目标的f.getName()属性的set方法
//因为知道是int类型的属性,所以传个int过去就是了。。实际情况中需要判断下他的参数类型
}
//疑问如果属性字段没有set方法,是否可以执行成功?
//读数据
for (Field f : fields) {
PropertyDescriptor pd = new PropertyDescriptor(f.getName(), clazz);
Method rM = pd.getReadMethod();//获得读方法
Integer num = (Integer) rM.invoke(obj);
System.out.println(num);
}
二、BeanWrapper和MutablePropertyValues
该2个类可以完成对已经实例化的对象属性进行设置值
BeanWrapper和MutablePropertyValues的使用案例
通过实例对象,给实例对象的属性赋值
public class TestMutablePropertyValues {
public static void main(String[] args) {
//Apple有2个属性id和name
String[] properties = new String[]{"id", "name"};
MutablePropertyValues pvs = new MutablePropertyValues();
for(int i=0; i<properties.length; i++){
String property = properties[i];
String value = "test" + i;
pvs.add(property, value);
}
Apple p = new Apple();//注意Apple里面属性的set和get方法不能少,不然报错
BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(p);
wrapper.setPropertyValues(pvs);//此时已经通过BeanWrapper 更改了Apple的实例对象属性
System.out.println(p);
}
}
输出:
Apple(id=test0, name=test1)
@Override
public void setValue(final Object object, Object valueToApply) throws Exception {
final Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
this.pd.getWriteMethod());
//上面的this.pd字段,就是PropertyDescriptor类型
final Object value = valueToApply;
writeMethod.invoke(getWrappedInstance(), value);
}
其实底层用的就是PropertyDescriptor来处理的
Spring使用场景
那么Spring在实例化Mapper的时候,也正是通过这种方式,来完成对Bean里面的属性赋值
比如下面代码:
//mbd是Mapper转成的DB,最总得到beanInstance也就是Mapper的实例 Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent); BeanWrapper bw = new BeanWrapperImpl(beanInstance); initBeanWrapper(bw); return bw;
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
相关文章
SpringBoot整合Redis使用@Cacheable和RedisTemplate
本文主要介绍了SpringBoot整合Redis使用@Cacheable和RedisTemplate,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2022-07-07
SpringBoot如何使用RequestBodyAdvice进行统一参数处理
这篇文章主要介绍了SpringBoot使用RequestBodyAdvice进行统一参数处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-06-06
Java在排序数组中查找元素的第一个和最后一个位置的方法详解
相信大家在操作Java的时候经常会要在一个数组(无序)中查找元素的第一个和最后一个位置,下面这篇文章主要给大家介绍了关于Java在排序数组中查找元素的第一个和最后一个位置的相关资料,需要的朋友可以参考下2024-01-01


最新评论