XStream叶子element转换器

背景

<student Id="1" ClassId="2">小王八</studuent>
@XStreamAlias("student")
public class Student {
	@XStreamAlias("Id")
    @XStreamAsAttribute
	private String id;
	
	@XStreamAlias("ClassId")
    @XStreamAsAttribute
	private String classId;
	
	private String value;
	
	// omit setters and getters
}

像这种把bean的某个属性当成value值得,目前的XStream还没找到解决方法

实现Converter接口

public class StudentXStreamConverter implements Converter {
	  @Override
    public void marshal(Object o, HierarchicalStreamWriter hierarchicalStreamWriter, MarshallingContext marshallingContext) {
        final Student student = (Student ) o;  
        hierarchicalStreamWriter.addAttribute("id",student.getId());
        hierarchicalStreamWriter.addAttribute("classId",student.getClassId());
        hierarchicalStreamWriter.setValue(student.getValue());
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader hierarchicalStreamReader, UnmarshallingContext unmarshallingContext) {
        final Student stduent = new Student ();// 在解析attribute元素时,先创建一个对象
   		stduent.setId(hierarchicalStreamReader.getAttritute("id));
   		stduent.setClassId(hierarchicalStreamReader.getAttritute("classId));
   		stduent.setVaue(hierarchicalStreamReader.getValue();
        return stduent ;
    }

    @Override
    public boolean canConvert(Class clazz) {
        return clazz == Student.class;
    }
}

这种写法100个bean就要写100份差不多的代码,显然不合适

重复功能抽象到父类

/**
 * @param <T> 支持的转换类型,T 必须有一个无参构造函数 {@link #newInstance()}
 * @author len
 */
public abstract class AbstractXStreamConverter<T> implements Converter {

    protected final Class<T> clazz;

    public AbstractXStreamConverter() {
        clazz = parseClazz();
    }

    @SuppressWarnings("unchecked")
    private Class<T> parseClazz() {
        val genericSuperclass = getClass().getGenericSuperclass();
        ParameterizedType superclass = (ParameterizedType) genericSuperclass;
        return (Class<T>) superclass.getActualTypeArguments()[0];
    }

    @Override
    @SuppressWarnings("unchecked")
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
        doMarshal((T) source, writer, context);
    }

    @Override
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
        final T instance = newInstance();
        doUnmarshal(instance, reader, context);
        return instance;
    }

    protected abstract void doMarshal(T source, HierarchicalStreamWriter writer, MarshallingContext context);

    protected abstract void doUnmarshal(T instance, HierarchicalStreamReader reader, UnmarshallingContext context);

    @Override
    public boolean canConvert(Class type) {
        return type == clazz;
    }

    protected T newInstance() {
        try {
            Constructor<T> constructor = clazz.getConstructor();
            if (constructor == null) {
                throw new IllegalArgumentException("必须提供无参构造器");
            }
            return constructor.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
}

基于反射,抽取了canConvert,类型转化以及创建实例的过程

进一步特性化,使用元数据反射序列化和反序列化

/**
 * 元数据收集器接口
 *
 * @author len
 */
@FunctionalInterface
public interface MetaInfoCollector<T> {

    T collect(Class<?> clazz);
}
/**
 * 元数据
 * @author len
 */
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true)
@Getter
public class PropertyManager {
    
    private Method reader;

    private Method writer;

    private String name;
}


/**
 * @author len
 */            
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
@Getter
public class PropertyManagers {
    @Nullable
    PropertyManager value;

    @Nullable
    List<PropertyManager> attributes;
}

/**
 * @param <T> {@link AbstractXStreamConverter} T 必须是一个叶子元素,必须符合java bean规范,且所有的属性必须是{@code String }类型
 * @author len
 */
public abstract class BaseMetaLeafElementXStreamConverter<T> extends AbstractXStreamConverter<T> implements MetaInfoCollector<PropertyManagers> {

    private static final Map<Class<?>, PropertyManagers> CACHE = new ConcurrentHashMap<>(64);

    public BaseMetaLeafElementXStreamConverter() {
        initMetaInfo();
    }

    private void initMetaInfo() {
        PropertyManagers propertyManagers = CACHE.get(clazz);
        if (propertyManagers == null) {
            synchronized (clazz) {
                // noinspection ConstantConditions
                if (propertyManagers == null) {
                    CACHE.put(clazz, collect(clazz));
                }
            }
        }
    }

    @Override
    protected void doMarshal(T source, HierarchicalStreamWriter writer, MarshallingContext context) {
        val propertyManagers = CACHE.get(clazz);

        try {
            val attributes = propertyManagers.getAttributes();
            if (!CollectionUtils.isEmpty(attributes)) {
                for (PropertyManager attribute : attributes) {
                    writer.addAttribute(attribute.getName(), toEmptyStringIfNull(attribute.getReader().invoke(source)));
                }
            }
            val value = propertyManagers.getValue();
            if (value != null) {
                writer.setValue(toEmptyStringIfNull(value.getReader().invoke(source)));
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected void doUnmarshal(T instance, HierarchicalStreamReader reader, UnmarshallingContext context) {
        val propertyManagers = CACHE.get(clazz);
        val attributes = propertyManagers.getAttributes();
        try {
            if (!CollectionUtils.isEmpty(attributes)) {
                for (PropertyManager attribute : attributes) {
                    val attributeValue = reader.getAttribute(attribute.getName());
                    attribute.getWriter().invoke(instance, attributeValue);
                }
            }
            val value = propertyManagers.getValue();
            if (value != null) {
                value.getWriter().invoke(instance, reader.getValue());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static String toEmptyStringIfNull(Object object) {
        return object == null ? "" : object.toString();
    }


}

使用XStream原生注解作为元数据源

/**
 * 基于XStream原生注解的实现
 * @param <T> T {@link BaseMetaLeafElementXStreamConverter}
 * @author len
 */
public abstract class XStreamAnnotationLeafElementConverter<T> extends BaseMetaLeafElementXStreamConverter<T> {

    @Override
    public PropertyManagers collect(Class<?> clazz) {

        try {
            val beanInfo = Introspector.getBeanInfo(clazz);
            val propertyDescriptors = beanInfo.getPropertyDescriptors();
            val propertyManagers = new ArrayList<PropertyManager>();
            PropertyManager valuePropertyManager = null;
            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                String name = propertyDescriptor.getName();
                if (name.equals("class")) {
                    continue;
                }
                if (name.equals("value")) {
                    valuePropertyManager = new PropertyManager(propertyDescriptor.getReadMethod(), propertyDescriptor.getWriteMethod(), "value");
                    continue;
                }
                val field = clazz.getDeclaredField(name) != null ? clazz.getDeclaredField(name) : clazz.getField(name);
                if (field != null) {
                    val attribute = field.getAnnotation(XStreamAsAttribute.class);
                    if (attribute != null) {
                        String value = name;
                        val alias = field.getAnnotation(XStreamAlias.class);
                        if (alias != null) {
                            value = alias.value();
                        }
                        propertyManagers.add(new PropertyManager(propertyDescriptor.getReadMethod(), propertyDescriptor.getWriteMethod(), StringUtils.isEmpty(value) ? name : value));
                    }
                }
            }
            return new PropertyManagers(valuePropertyManager, propertyManagers);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
}

demo


public class StudentConverter extends XStreamAnnotationLeafElementConverter<Student> {
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值