Spring BeanWrapper

BeanWrapper这个接口主要用来操作一些标准的JavaBeans。对Bean属性的操作,封装了一个bean的行为,诸如设置和获取属性值等。大家熟知的主要有下面的工具类(Apache的BeanUtils和PropertyUtils、cglib的BeanMap和BeanCopier、spring的BeanUtils),但是Spring里有有一个更加强大的BeanWrapper操作类(支持设置嵌套属性、支持属性值的类型转换(设置ConversionService)。

实例:

public class AppTest {
    @Test
    public void shouldAnswerWithTrue() {
        Staff staff = new Staff();
        BeanWrapper staffWrapper = new BeanWrapperImpl(staff);
        //设置属性
        staffWrapper.setPropertyValue("id", "1001");
        //设置属性
        staffWrapper.setPropertyValue(new PropertyValue("name", "小王"));
        //设置属性
        staffWrapper.setPropertyValue("hobbies[0]", "羽毛球");
        staffWrapper.setPropertyValue("hobbies[1]", "篮球");
        System.out.println("================");
        //获取属性
        Object id = staffWrapper.getPropertyValue("id");
        System.out.println("id="+id);
        //获取属性
        Object name = staffWrapper.getPropertyValue("name");
        System.out.println("name="+name);
        //获取属性
        Object hobbies = staffWrapper.getPropertyValue("hobbies");
        System.out.println("hobbies="+hobbies);
        //获取属性
        Object hobbies_0 = staffWrapper.getPropertyValue("hobbies[0]");
        System.out.println("hobbies[0]="+hobbies_0);
        System.out.println("================");
        System.out.println("staff="+staff.toString());
        System.out.println("================");
        Company company = new Company();
        BeanWrapper companyWrapper = new BeanWrapperImpl(company);
        companyWrapper.setPropertyValue("staffs[" + staff.getId() + "]", staff);
        System.out.println(company.getStaffs().get(staff.getId()));
    }
}

class Staff {
    private String id;
    private String name;
    private List<String> hobbies = new ArrayList<>();

    public void setId(String id) {
        System.out.println("setId 方法被调用");
        this.id = id;
    }

    public void setName(String name) {
        System.out.println("setName 方法被调用");
        this.name = name;
    }

    public String getId() {
        System.out.println("getId 方法被调用");
        return id;
    }

    public String getName() {
        System.out.println("getName 方法被调用");
        return name;
    }

    public List<String> getHobbies() {
        System.out.println("getHobbies 方法被调用");
        return hobbies;
    }

    public void setHobbies(List<String> hobbies) {
        System.out.println("getHobbies 方法被调用");
        this.hobbies = hobbies;
    }


    @Override
    public String toString() {
        return "Staff{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", hobbies=" + Arrays.toString(hobbies.toArray()) +
                '}';
    }
}

class  Company{
    private Map<String, Staff> staffs = new HashMap<>();
    public Map<String, Staff> getStaffs() {
        return staffs;
    }
    public void setStaffs(Map<String, Staff> staffs) {
        this.staffs = staffs;
    }
}

结果:

setId 方法被调用
setName 方法被调用
getHobbies 方法被调用
getHobbies 方法被调用
================
getId 方法被调用
id=1001
getName 方法被调用
name=小王
getHobbies 方法被调用
hobbies=[羽毛球, 篮球]
getHobbies 方法被调用
hobbies[0]=羽毛球
================
staff=Staff{id='1001', name='小王', hobbies=[羽毛球, 篮球]}
================
getId 方法被调用
getId 方法被调用
Staff{id='1001', name='小王', hobbies=[羽毛球, 篮球]}

这个例子中,BeanWapper对Bean进包装,暴露统一的修改、查询 bean属性的方法,然后通过反射的方式调用Bean的get、set方法。

 

BeanWapper的继承关系:

 

BeanWrapper 继承上述三个接口,那么它就具有三重身份:

  • 属性编辑器
  • 属性编辑器注册表
  • 类型转换器

ConfigurablePropertyAccessor
BeanWrapper 同时继承 ConfigurablePropertyAccessor,其做了一些额外的扩展

由于 TypeConverter 是基于线程不安全的 PropertyEditors ,因此 TypeConverters 本身也不被视为线程安全,在 Spring 3 后,不在采用 PropertyEditors 类作为 Spring 默认的类型转换接口,而是采用 ConversionService 体系,但 ConversionService 是线程安全的,所以在 Spring 3 后,如果你所选择的类型转换器是 ConversionService 而不是 PropertyEditors 那么 TypeConverters 则是线程安全的
 

public interface ConfigurablePropertyAccessor extends PropertyAccessor, PropertyEditorRegistry, TypeConverter {
	/**
	 * 指定用于转换属性值的Spring3.0 ConversionService,作为JavaBeans属性编辑器的替代方法。
	 */
	void setConversionService(@Nullable ConversionService conversionService);

	/**
	 * 返回关联的ConversionService(如果有)
	 */
	@Nullable
	ConversionService getConversionService();
 
	/**
	 *
	 * 设置在将属性编辑器应用于属性的新值时是否提取旧属性值
	 */
	void setExtractOldValueForEditor(boolean extractOldValueForEditor);
 
	/**
	 * 返回在将属性编辑器应用于属性的新值时是否提取旧属性值。
	 */
	boolean isExtractOldValueForEditor();
 
	/**
	 * Set whether this instance should attempt to "auto-grow" a
	 * nested path that contains a {@code null} value.
	 * <p>If {@code true}, a {@code null} path location will be populated
	 * with a default object value and traversed instead of resulting in a
	 * {@link NullValueInNestedPathException}.
	 * <p>Default is {@code false} on a plain PropertyAccessor instance.
	 */
	void setAutoGrowNestedPaths(boolean autoGrowNestedPaths);
 
	/**
	 * Return whether "auto-growing" of nested paths has been activated.
	 */
	boolean isAutoGrowNestedPaths();
}

参考:https://blog.csdn.net/qq330983778/article/details/88921230

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值