当前位置: 首页 > Java > 正文

xstream 对象强转失败

1 星2 星3 星4 星5 星 (暂无评分)
Loading ... Loading ...
baidu_share

昨天,同事为了优化性能把序列化工具类修改了。

public class XmlSerializableTool {
 
    /**
     * xStream序列化
     */
    private static final ThreadLocal<XStream> serializeHolder = new ThreadLocal<XStream>();
 
    /**
     * xStream反序列化
     */
    private static final ThreadLocal<XStream> deserializeHolder = new ThreadLocal<XStream>();
 
    private static String xmlHeader="<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n";
 
 
    public static String serializeXML(Object obj, boolean flag) {
        XStream xStreamSerialize = serializeHolder.get();
        if (xStreamSerialize == null) {
            xStreamSerialize = new XStream(new DomDriver());
            serializeHolder.set(xStreamSerialize);
        }
        if (flag) {
            xStreamSerialize.autodetectAnnotations(true);
        }
        StringBuilder sb=new StringBuilder();
        sb.append(xmlHeader).append(xStreamSerialize.toXML(obj));
        return sb.toString();
    }
 
    @SuppressWarnings("unchecked")
    public static <T> T deSerializeXML(Class<T> className, String xml, boolean flag) {
        XStream xStreamDeserialize = deserializeHolder.get();
        if (xStreamDeserialize == null) {
            xStreamDeserialize = new XStream(new DomDriver());
            deserializeHolder.set(xStreamDeserialize);
        }
        xStreamDeserialize.processAnnotations(className);
        if (flag) {
            xStreamDeserialize.autodetectAnnotations(true);
        }
        return (T) xStreamDeserialize.fromXML(xml);
    }
 
}

解决多线程并发问题,单例类,减少new对象造成内存浪费。

以前代码:

public class XmlSerializableTool {
 
    /**
     * xStream序列化/反序列化
     */
    private static XStream xStreamSerialize = new XStream(new XppDriver(new XmlFriendlyReplacer("_-", "_")));
 
    private static String xmlHeader="<?xml version='1.0' encoding='utf-16'?>\r\n";
 
    /**
     * 序列化
     * 
     * @param obj
     *            需要系列化的对象
     * @param flag
     *            是否需要首字母大写 true是表示需要(利用标签系列化)
     * @return
     */
    public static String serializeXML(Object obj, boolean flag) {
 
        if (flag) {
            xStreamSerialize.autodetectAnnotations(true);
        }
        StringBuilder sb=new StringBuilder();
        sb.append(xmlHeader).append(xStreamSerialize.toXML(obj));
        return sb.toString();
    }
 
    /**
     * 反序列化
     * 
     * @param <T>
     * @param type
     * @param xmlObj
     * @param flag
     *            是否需要利用标签 反系列化 true,表示需要
     * @return
     */
    public static <T> T deSerializeXML(Class<?> type, String xmlObj, boolean flag) {
        XStream xStream = new XStream(new DomDriver()) {
 
            protected MapperWrapper wrapMapper(MapperWrapper next) {
                return new MapperWrapper(next) {
 
                    public boolean shouldSerializeMember(Class definedIn, String fieldName) {
                        try {
                            return definedIn != Object.class || realClass(fieldName) != null;
                        } catch (CannotResolveClassException cnrce) {
                            return false;
                        }
                    }
                };
            }
        };
 
        /** 如果有标注,则类别用用标注, 如果没有则用类名 */
        for (Annotation at : type.getAnnotations()) {
            if (at instanceof XStreamAlias) {
                XStreamAlias alias = (XStreamAlias) at;
                if (alias.value() != null) {
                    xStream.alias(alias.value(), type);
                    break;
                }
            }
        }
        xStream.alias(type.getSimpleName(), type);
        /** 如果有标注,则类别用用标注, 如果没有则用类名 end */
 
        if (flag) {
            xStream.autodetectAnnotations(true);
        }
        return (T) xStream.fromXML(xmlObj);
    }
 
}

xstream maven依赖:

<dependency>
			<groupId>com.thoughtworks.xstream</groupId>
			<artifactId>xstream</artifactId>
			<version>1.4.2.2</version>
		</dependency>

优化代码上线后,报**.Order不能强制转换为TransferOrder。
查看代码TransferOrder别名就叫Order。

@XStreamAlias("Order")
public class TransferOrder implements Serializable {
 
    private static final long serialVersionUID = 6320907904541696916L;
 
    /**
     * 订单ID (基本信息)
     */
    @XStreamAlias("Id")
    private long id;
...
}

报错的**.Order发现别名也叫Order。
进入xstream源码查看processAnnotations方法

public void processAnnotations(Class[] types)
  {
    if (this.annotationConfiguration == null) {
      throw new InitializationException("No com.thoughtworks.xstream.mapper.AnnotationMapper available");
    }
    this.annotationConfiguration.processAnnotations(types);
  }
 
  public void processAnnotations(Class type)
  {
    processAnnotations(new Class[] { type });
  }

会调用AnnotationMapper的processAnnotations方法

public void processAnnotations(Class[] initialTypes)
  {
    if ((initialTypes == null) || (initialTypes.length == 0)) {
      return;
    }
    this.locked = true;
    synchronized (this.annotatedTypes)
    {
      Set<Class<?>> types = new UnprocessedTypesSet(null);
      for (Class initialType : initialTypes) {
        types.add(initialType);
      }
      processTypes(types);
    }
  }
 
  private void processAnnotations(Class initialType)
  {
    if (initialType == null) {
      return;
    }
    synchronized (this.annotatedTypes)
    {
      Set<Class<?>> types = new UnprocessedTypesSet(null);
      types.add(initialType);
      processTypes(types);
    }
  }
private void processTypes(Set<Class<?>> types)
  {
    while (!types.isEmpty())
    {
      Iterator<Class<?>> iter = types.iterator();
      Class<?> type = (Class)iter.next();
      iter.remove();
      if ((this.annotatedTypes.add(type)) && 
        (!type.isPrimitive()))
      {
        addParametrizedTypes(type, types);
 
        processConverterAnnotations(type);
        processAliasAnnotation(type, types);
        if (!type.isInterface())
        {
          processImplicitCollectionAnnotation(type);
 
          Field[] fields = type.getDeclaredFields();
          for (int i = 0; i < fields.length; i++)
          {
            Field field = fields[i];
            if ((!field.isEnumConstant()) && 
              ((field.getModifiers() & 0x88) <= 0))
            {
              addParametrizedTypes(field.getGenericType(), types);
              if (!field.isSynthetic())
              {
                processFieldAliasAnnotation(field);
                processAsAttributeAnnotation(field);
                processImplicitAnnotation(field);
                processOmitFieldAnnotation(field);
                processLocalConverterAnnotation(field);
              }
            }
          }
        }
      }
    }
  }

关键点在于:存在两个Order别名,会把第一个Order别名加人进去,后面的则不会加,所以序列化对象时候会导致强转错误。

TransferOrder transfer = XmlSerializableTool.deSerializeXML(TransferOrder.class, task.getInfo(), true);有问题代码

解决方法:每次new XStream对象。使用完后将对象置为null,该对象使用若引用。

xStreamDeserialize.processAnnotations(TransferOrder.class);
            xStreamDeserialize.autodetectAnnotations(true);
            WeakReference<XStream> wrXStrem=new WeakReference<XStream>(xStreamDeserialize);
            TransferOrder transfer =(TransferOrder)wrXStrem.get().fromXML(task.getInfo());

本文固定链接: http://www.chepoo.com/xstream-object-cast-failure.html | IT技术精华网

【上一篇】
【下一篇】

xstream 对象强转失败:等您坐沙发呢!

发表评论