Spring源碼如何修改Bean的屬性用到的相關類
關于Spring在處理Bean給屬性賦值,或者執(zhí)行實例化好的Bean的某些方法時,用到了好幾個類,下面看下這些都是怎么實現的
一、PropertyDescriptor
PropertyDescriptor類表示JavaBean類通過存儲器導出一個屬性,可以通過該類,完成對實例化好的Bean的某些方法調用
比如setxx或者getxxx,比如Spring在處理帶有@Autowired注解修飾的方法時,就是通過這個來完成調用的
該類常用的方法有:
Method getReadMethod() //獲得用于讀取屬性值的方法 Method getWriteMethod() //獲得用于寫入屬性值的方法
PropertyDescriptor的案例
1、通過反射創(chuàng)建TaskProvidePropsList實例
2、通過PropertyDescriptor拿屬性的set方法,修改屬性的值
Class clazz = Class.forName("TaskProvidePropsList");//拿到類clazz對象
Object obj = clazz.newInstance();//實例化
Field[] fields = clazz.getDeclaredFields();//拿到這個對象的所有屬性字段
//寫數據
for (Field f : fields) {
//創(chuàng)建PropertyDescriptor對象,設置需要改動哪個類的哪個屬性字段名
PropertyDescriptor pd = new PropertyDescriptor(f.getName(), clazz);
Method wM = pd.getWriteMethod();//獲得該屬性寫方法
wM.invoke(obj, 2);//其實這里是執(zhí)行目標的f.getName()屬性的set方法
//因為知道是int類型的屬性,所以傳個int過去就是了。。實際情況中需要判斷下他的參數類型
}
//疑問如果屬性字段沒有set方法,是否可以執(zhí)行成功?
//讀數據
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

