XStream是一个Java的工具库,主要用于将对象序列化成XML或者将XML反序列化成对象,主要用途是传输、持久化、配置、单元测试。
1、XStream的序列化转换
XStream主要用toXML和fromXML进行转换:
1 2
| XStream.toXML(obj) XStream.fromXML(str)
|
一个转换的例子,将Student实例进行序列化,转换成xml,然后转换回来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| public class Student implements Serializable { private String name; private int age; private School school;
public Student(String name, int age, School school) { this.name = name; this.age = age; this.school = school; }
private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); System.out.println("XML反序列化"); } }
public class School { private String name; private int classNum;
public School(String name, int classNum) { this.name = name; this.classNum = classNum; } }
public class Test { public static void main(String[] args){ XStream xStream = new XStream(); Student people = new Student("xiaoming", 25, new School("北京大学",500)); String xml = xStream.toXML(people); System.out.println(xml); Student object = (Student) xStream.fromXML(xml); } }
|
序列化后的XML字符串如下:
1 2 3 4 5 6 7 8 9 10 11 12
| <xstream.test.Student serialization="custom"> <xstream.test.Student> <default> <age>25</age> <name>xiaoming</name> <school> <name>北京大学</name> <classNum>500</classNum> </school> </default> </xstream.test.Student> </xstream.test.Student>
|
2、XStream序列化机制
重要部分 |
描述 |
AbstractDriver |
为XStream提供流解析器和编写器 |
MarshallingStrategy |
编组和解组策略的核心接口,两个方法:marshal-编组对象图、unmarshal-解组对象图 |
Mapper |
映射器,XML的elementName通过mapper获取对应类、成员、属性的class对象。支持解组和编组,所以方法是成对存在real 和serialized,他的子类MapperWrapper作为装饰者,包装了不同类型映射的映射器,如AnnotationMapper,ImplicitCollectionMapper,ClassAliasingMapper。 |
ConverterLookup |
通过Mapper获取的Class对象来得到相应的Class转换器,并将其转化成对应实例对象。DefaultConverterLookup是该接口的实现类,同时实现了ConverterRegistry的接口,具备查找converter功能和注册converter功能。 |
TreeMarshaller和TreeUnmarshaller |
树编组和树解组程序,调用mapper和Converter把XML转化成java对象,里面的start方法开始解组,convertAnother方法把class转化成java对象。它的抽象子类AbstractTreeMarshallingStrategy有抽象两个方法 createUnmarshallingContext createMarshallingContext 用来根据不同的场景创建不同的TreeUnmarshaller子类和TreeMarshaller子类,使用了策略模式,如ReferenceByXPathMarshallingStrategy创建ReferenceByXPathUnmarshaller,ReferenceByIdMarshallingStrategy创建ReferenceByIdUnmarshaller |
对象转xml字符串过程分析:
XStream.toXML方法如下,整个过程主要调用marshal处理,marshal主要用于编组对象图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public String toXML(Object obj) { Writer writer = new StringWriter(); this.toXML(obj, (Writer)writer); return writer.toString(); }
public void toXML(Object obj, Writer out) { HierarchicalStreamWriter writer = this.hierarchicalStreamDriver.createWriter(out);
try { this.marshal(obj, writer); } finally { writer.flush(); }
}
|
xStream.marshal()最终会调用到AbstractTreeMarshallingStrategy.marshal()
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public void marshal(Object obj, HierarchicalStreamWriter writer) { this.marshal(obj, writer, (DataHolder)null); }
public void marshal(Object obj, HierarchicalStreamWriter writer, DataHolder dataHolder) { this.marshallingStrategy.marshal(writer, obj, this.converterLookup, this.mapper, dataHolder); }
public void marshal(HierarchicalStreamWriter writer, Object obj, ConverterLookup converterLookup, Mapper mapper, DataHolder dataHolder) { TreeMarshaller context = this.createMarshallingContext(writer, converterLookup, mapper); context.start(obj, dataHolder); }
|
TreeMarshaller.start如下
1 2 3 4 5 6 7 8 9 10 11 12
| public void start(Object item, DataHolder dataHolder) { this.dataHolder = dataHolder; if (item == null) { this.writer.startNode(this.mapper.serializedClass((Class)null)); this.writer.endNode(); } else { ExtendedHierarchicalStreamWriterHelper.startNode(this.writer, this.mapper.serializedClass(item.getClass()), item.getClass()); this.convertAnother(item); this.writer.endNode(); } }
|
TreeMarshaller.convertAnother调用DefaultConverterLookup.lookupConverterForType找查找转换器
1 2 3 4 5 6 7 8 9 10 11 12
| public void convertAnother(Object item) { this.convertAnother(item, (Converter)null); }
public void convertAnother(Object item, Converter converter) { if (converter == null) { converter = this.converterLookup.lookupConverterForType(item.getClass()); } else if (!converter.canConvert(item.getClass())) { ... } this.convert(item, converter); }
|
通过DefaultConverterLookup.lookupConverterForType找到类对应的转换器,然后调用TreeMarshaller.convert进行转换。(AbstractReferenceMarshaller)TreeMarshaller.convert逻辑是调用对应转换器的doMarshal方法,如实现了Serializable的对象转换器是SerializableConverter,调用的是SerializableConverter.doMarshal
1 2 3 4 5 6 7
| public void convert(Object item, Converter converter) { if (this.getMapper().isImmutableValueType(item.getClass())) { converter.marshal(item, this.writer, this); } else { ... } }
|
SerializableConverter.doMarshal中核心是defaultWriteObject方法,该方法主要实现序列化所有属性域信息,和上面所述一样,按照属性的类对应的转换器来调用转换器的doMarshal方法,以此逻辑将所有属性信息序列化。比如本例中School对应的转换器是ReflectionConverter。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| public void defaultWriteObject() { boolean writtenDefaultFields = false; ObjectStreamClass objectStreamClass = ObjectStreamClass.lookup(currentType[0]); if (objectStreamClass != null) { ObjectStreamField[] fields = objectStreamClass.getFields(); for(int i = 0; i < fields.length; ++i) { ObjectStreamField field = fields[i]; Object value = SerializableConverter.this.readField(field, currentType[0], source); if (value != null) { if (!writtenClassWrapper[0]) { writer.startNode(SerializableConverter.this.mapper.serializedClass(currentType[0])); writtenClassWrapper[0] = true; }
if (!writtenDefaultFields) { writer.startNode("default"); writtenDefaultFields = true; }
if (SerializableConverter.this.mapper.shouldSerializeMember(currentType[0], field.getName())) { Class actualType = value.getClass(); ExtendedHierarchicalStreamWriterHelper.startNode(writer, SerializableConverter.this.mapper.serializedMember(source.getClass(), field.getName()), actualType); Class defaultType = SerializableConverter.this.mapper.defaultImplementationOf(field.getType()); if (!actualType.equals(defaultType)) { String attributeName = SerializableConverter.this.mapper.aliasForSystemAttribute("class"); if (attributeName != null) { writer.addAttribute(attributeName, SerializableConverter.this.mapper.serializedClass(actualType)); } }
context.convertAnother(value); writer.endNode(); } } }
if (writtenClassWrapper[0] && !writtenDefaultFields) { writer.startNode("default"); writer.endNode(); } else if (writtenDefaultFields) { writer.endNode(); }
} }
|
除了默认的序列化方法,在SerializableConverter.doMarshal中支持重写方法writeObject的调用,所以当类实现了Serializable并且重写了writeObject,则会调用重写的writeObject。一般在重写的writeObject方法中还是会调用SerializableConverter.defaultWriteObject方法来进行属性的序列化。
1
| this.serializationMembers.callWriteObject(currentType[0], source, objectOutputStream);
|
反序列化fromXML类似,不再分析。
3、总结
不论是xml形式还是json形式还是Java原生序列化,本质都是将对象以某种形式表现出来,各种形式的序列化最终都是序列化类信息和该对象的属性域信息。
4、参考链接
https://www.jianshu.com/p/387c568faf62